WM DOTTEDFOCUS

From WxWiki
Jump to navigation Jump to search

How to make the dotted appearance work on Windows 2000

Currently, when controls have the focus and can accept keyboard input on MS Windows, they do not have the exact same appearance as other MS Windows programs. For example, a combo box with the focus has a dark, blue background but does not have a dotted rectangle around the selected entry.

I researched the problem using Google and only found one (short) discussion of this topic. It was called "wxWin 2.4.0: dotted rectangles around active controls missing" and posted in Jan 2003. It can be found here: http://lists.wxwidgets.org/archive/wx-users/msg30483.html

I got it to work by sending an undocumented MS Windows message to the control or its parent or its grandparent, etc. By sending this message to any parent window, all child windows show the dotted focus rectangle, if appropriate. I've call this message: WM_DOTTEDFOCUS (0x128). MS Windows does not seem to be picky: you can send this message before or after you add controls to a parent. To make it work, you just do a ::SendMessage() with WM_DOTTEDFOCUS with 0x30002 in WPARAM and 0 in LPARAM.

I discovered this undocumented MS Windows message by using Microsoft Spy++ from Visual C++ 6.0. I named it WM_DOTTEDFOCUS simply so it would be easier to find and discuss the message. (I searched Google but found no other name or even any mention of this message.) I don't really know anything about this message. I don't know what are the possible argument values nor do I know what they mean. I've also only tried it on my own Windows 2000 box so it might or might not work for you. I also hacked the wxWindows source to put this call in wxDialog::Create(); it seemed to work.

Here's some sample code (based on wxWindows 2.4.0):

<html><code> wxDialog dlg(NULL, "Dialog", true);

 #ifdef __WXMSW__
 // magic incantation: show focused controls with dotted lines
 UINT WM_DOTTEDFOCUS = 0x128;
 
 ::SendMessage((HWND)dlg.GetHWND(), WM_DOTTEDFOCUS, 0x30002, 0);
 #endif __WXMSW__
 
 // nothing important below this line
 wxWindow * pWndPanel = &dlg;
 
 // comment the next line to put the combo box directly on the dialog
 pWndPanel = new wxPanel(&dlg, wxID_ANY, wxPoint(20, 20), wxSize(100, 100), wxTAB_TRAVERSAL | wxSIMPLE_BORDER);
 
 wxString choices[4] = { "value1", "value2", "value3", "value4" };
 wxComboBox * pWndCb = new wxComboBox(pWndPanel, wxID_ANY, "value1", wxPoint(20, 20), wxDefaultSize, 4, choices, wxCB_READONLY);
 
 pWndCb->SetSize(pWndCb->GetBestSize());
 
 dlg.ShowModal();</code></html>

About the author

Feel free to e-mail me at <html><a href="mailto:[email protected]%22>[email protected]</a></html> with any questions or comments.