Tips'n'Tricks

Below are some random tricks that I found on the web or in MSDN; I collected them here in case someone else is google'ing for them, and for personal future reference (my memory is crap).

(c) 2001 by Bert Peers / Last Update : 27/11/2001 / bpeers@acm.org - Mail me your comments and ideas !

 

Win2000 Reboot

If something ugly happens due to a driver issue, you get an instantaneous reboot. This is actually a feature, supposed to help improve the uptime of servers. For developing, a BSOD could be more useful. Disable it using the Control Panel : System, Advanced, Start Up and Recovery : Automatically Reboot...

 

cmd.exe Autocompletion

If you start cmd.exe with the /f flag, you get autocompletion using Ctrl-D for directories and Ctrl-F for filenames. It gets better though; go to HKEY_CURRENT_USER\Software\Microsoft\Command Processor and change CompletionChar and PathCompletionChar to 9. Now hitting TAB will work for both files and paths. No bash-style appending of a \ though.

 

#ifdef'd MSVC resources

An .rc file can be #ifdef'd like any other. The trick however is that MSVC uses a separate precompiler to parse the resources. If you were wondering why #ifdef DEBUG is recognized, but #ifdef CUSTOM apparently isn't, here's why : define the symbols in Project Settings, Resources, Preprocessor Definitions. That would typically be a copy/paste of Project Settings, C/C++, Preprocess Definitions.

Beware that editing any resource in MSVC will completely rewrite the .rc file ! The best thing to do is pull all #ifdef'd resources out of the .rc entirely, for example by putting them in res\yourproject.rc2. Alternatively make a new .rc file, say custom.rc and add an #include to the "Resource Compile-time Directives" : right click on the top of the resources tree, select "Resource Includes...", and add #include "custom.rc" at the bottom of the "Compile-time Directives" box.

 

WM_CHAR in a dialog

If you've built a custom control by inheriting (indirectly) from CWnd (or using Win32), you may have noticed that it works fine standalone, but fails to pick up any WM_CHAR or WM_KEYDOWN messages when used as a control in a dialog. The reason is that the message pump will give Win32 a first shot at processing these messages, so that eg. TAB results in a focus change, and VK_DOWN goes to the next radio button in a group. This is done by ::IsDialogMessage ().

To change this, update the control's WindowProc to handle WM_GETDLGCODE and return DLGC_WANTALLKEYS.

 

A better #pragma message

When outputting a message in MSVC using #pragma message Some notice, you can prepend the filename and linenumber using the same format as the Build or Find In Files command. This will make the printed string clickable/F4'able. A good way to do this is using a macro; the trick to printing the line number using __LINE__ is to expand it twice :
#define STR(x)  #x
#define STR2(x) STR(x)
#define NOTE(x) message (__FILE__ "(" STR2(__LINE__) ") : -NOTE- " #x)    

#pragma NOTE(Need to redo this)
when compiled will output
c:\Develop\Test.cpp(14) : -NOTE- Need to redo this
and doubleclicking on the line opens test.cpp, at line 14.

 

Replacing the statusbar's "Ready"

If you use an MFC generated App, it has a string called AFX_IDS_IDLEMESSAGE in the string table containing "Ready", which is shown when the mainframe is idle. You can simply replace it to print something else. However, if you want to change the string dynamically, you need something more obscure : handling WM_SETMESSAGESTRING.

In CMainFrame, add a function like

LRESULT OnSetMessageString (WPARAM wParam, LPARAM lParam);
In the messagemap, add
ON_MESSAGE (WM_SETMESSAGESTRING, OnSetMessageString)
You'll need to define the message using
#define WM_SETMESSAGESTRING 0x0362
You can then scan for AFX_IDS_IDLEMESSAGE in OnSetMessageString and replace it with anything you want, such as a string you store in some std::string m_statustext; :
LRESULT CMainFrame::OnSetMessageString (WPARAM wParam, LPARAM lParam)
{
  if (wParam == AFX_IDS_IDLEMESSAGE && m_statustext.c_str ()[0] != 0)
    return CFrameWnd::OnSetMessageString (0, (LPARAM)m_statustext.c_str ());
  return CFrameWnd::OnSetMessageString (wParam, lParam);
}

 
 

Back to my homepage