You can get a pointer to a control from a already created dialog control by doing a simple typecast of the results from GetDlgItem. Here's an example that creates a CButton from a checkbox with ID : IDC_CHECK1.
Note that it's always safer to check for the validity of the results from GetDlgItem.
scot@stingray.com, 6/1/95
Read the documentation on SubClassDlgItem. Here's an example of how to call it:
Mike Williams, mikew@marlin.ssnet.com, mfc-l 6/1/95
Make sure that you subclass the control BEFORE you call Ctl3dSubclassDlg, if the 3-d control DLL is loaded first, it will already have subclassed your controls and you will get an assert.
Mike Williams, mikew@marlin.ssnet.com, mfc-l 6/1/95
NOTE: This is in the Microsoft Software Library.
The FCSVAL sample application was created to show how an application can do control-by-control validation in a dialog box.
The application itself is just a modal dialog box displayed by the CWinApp::InitInstance(). After displaying the dialog box, InitInstance() simply quits the application.
The important part of the sample takes place in the dialog-box class implementation: There are two edit controls. The first takes input of an integer between 1 and 20. The second takes a character string as input with length less than or equal to 5. When you Tab or mouse-click from control to control within the displayed dialog box, the contents of the control that is losing focus are validated.
The CFocusDlg Class
The application's functionality centers around the CFocusDlg class and its implementation of four message handlers (discussed below). Normal data exchange (DDX) and validation (DDV) using the routines provided by MFC take place in OnInitialUpdate(), when the dialog box is first displayed, and when the user chooses the OK button to accept the input. This is default behavior provided by ClassWizard when member variables are connected to dialog-box controls and can be examined in the dialog class DoDataExchange() function.
Validating control contents when switching focus from one control to the next is done by handling the EN_KILLFOCUS notification sent by the edit control that is losing focus. The idea here is to check the contents and, if they are not valid, to display the message box, inform the user, and then set the focus back to the control from which it came. Unfortunately, some difficulties arise when trying to set the focus (or display the message boxes) within a killfocus message handler. At this point, Windows is in an indeterminate state as it is moving focus from one control to the other. This is a bad place to do the validation and SetFocus() call.
The solution here is to post a user-defined message to the dialog box (parent) and do the validation and SetFocus() there, thus waiting for a safer time to do the work. (See "CFocusDlg::OnEditLostFocus()" in the file FOCUSDLG.CPP and "WM_EDITLOSTFOCUS user-defined message" in the file FOCUSDLG.H.)Another thing you will notice about this function is that it uses TRY/CATCH to do the validation. The provided DDX/DDV routines throw CUserExceptions when failing to validate or load a control's data. You should catch these and do the SetFocus() in the CATCH block.
Note: This sample has other cool stuff, but this is the major one I've seen asked about on the Net.
MS FAQ, 6/25/95
I don't know about a magic way to do this using a single HWND, but there is a simple and self-documenting technique that I've been using for a long time. You can make a routine that accepts an array of UINTs (your control IDs) and a visibility flag.This function can be a stand-alone function, or you can put it inside a class. I have been collecting little utility functions like this and keep them in a CDialogBase class -- when I create a new dialog box in ClassWizard, I fix up the code to derive from CDialogBase instead of CDialog.
For example, the function might look like this:
Then later, often in your OnInitDialog handler, you can call this function with your control group:
You can find many uses for these control arrays later too... (Changing fonts in a series of controls, etc...) Good luck,
jmccabe@portage1.portup.com, mfc-l, 7/18/95
Your dialog can trap the WM_CTLCOLOR message, look up the MFC help file notes for CWnd::OnCtlColor(). Before a control is about to paint itself, the parent window receives a chance to set its own default text color and background brush.
jmccabe@portage1.portup.com, mfc-l, 7/18/95
Also check out the MS KB article ID: Q117778 TITLE: Changing the Background Color of an MFC Edit Control.
Ramesh, MSMFC, 7/19/95
Handle WM_GETDLGCODE and return the appropriate value. Remember that the listbox (or any other control) can only handle keyboard input when it has the focus.
joej@golddisk.com, programmer.misc, 8/21/95, programmer.misc
Download MLBDDX.ZIP from the MSMFC library on CIS. You'll get all the necessary code. When the dialog closes, a provided CStringList will be filled with the selected items. Freeware.
-Patrick Philippot, CIS email, 8/3/95
NOTE: THE METHOD IN 6.2.6 WILL NOT WORK FOR BUTTONS!
If you want to change the color of a dialog button, you have to use owner-draw button. (you can use bitmap buttons) Changing the color through OnCtlColor() will not work for buttons. The following Knowledge Base articles (GO MSKB on CIS) may be of help to you.
ID: Q32685 TITLE: Using the WM_CTLCOLOR Message
ID: Q64328 SAMPLE: Owner-Draw: 3-D Push Button Made from Bitmaps with Text
This article explains sample code for a owner-draw button.
Ramesh, NetQuest., MSMFC, 8/3/95
Make sure that the lines are separated with \r\n, not just \n.
sutor@watson.ibm.com, mfc-l, 8/7/95
jahans@slb.com, mfc-l, 8/25/95
Or:
Look into the mfc sample - npp - npview.cpp! Turns out all combo's create their edits with an ID of 1001 (decimal) so - if pComboBox is the pWnd object pointing to the combo - all you need is:
scot@stingray.com
mikem@abelcomputers.com, email, 9/7/95
[ed note: Ok, this probably isn't a FAQ, but I thought it sounded pretty cool.]
I have a fix, but you may not like it; however, it takes care of both subclassing methods.
If SubclassWindow() was virtual, all problems would be solved, as SubclassDlgItem calls SubclassWindow(), and common initialization could be called from this point, and from OnCreate(). Even better would be a virtual SetupWindow() function called from all initialization points by Microsoft's code.
C'est la vie. My fix might slow the message loop for the control in question, but so far I haven't seen any performance hits. Over-ride the virtual function WindowProc() for your control something like the following (call SetupWindow() in OnCreate() also):
Jody Power (jodyp@andyne.on.ca)