I need to capture the control handles of every INPUT type control (TextBox, etc) on a form and put them in an array.
I would have thought that some CUSTOM message in each control could be used but it seems the ones I guessed like wm_create are not there for controls only forms.
There is a FF_DESTROY but not create.
I know I could use EnumChildWindows for a form but it does not tell me which control is which.
My ideal would be in the CUSTOM message for each control I wanted I could detect and save the handle.
Thanks.
Would it be possible to use a WM_CREATE in the CUSTOM section for each control and gather the info you need there?
James,
I tried in the CUSTOM event with
if wMsg = %wm_create
but it never fires.
That is EXACTLY what I need but ....
Thanks --- I will keep looking.
A little debugging says during startup these fire for each control and can be caught in the CUSTOM event:
07 WM_SETFOCUS
08 WM_KILLFOCUS
0e WM_GETTEXTLENGTH
30 WM_SETFONT
c5 EM_LIMITTEXT
Since I don't change fonts I suppose that one would work.
EnumChildWindows is probably your best bet, then getting the Class Name (GetClassName) of each returned like "Edit", etc. I used it in my Bible Processing app...if Michael ever posts the code...that tested what type of control the mouse was over to not change the pointer on Edit controls and such so the I Beam cursor stayed.
Or, you could just use the handle names and add each to the array manually if there isn't many. FF also has control arrays built in, so you can have it do the work.
You will never see WM_CREATE messages for child controls. This is standard behaviour for child controls. The WM_CREATE is buried somewhere inside Microsoft's code for the class. FireFly creates the control and then subclasses it. That is why you have access to messages that you would not normally have access to (e.g. the WM_CHAR in a TextBox).
You can get a WM_CREATE message for a child control, but it basically involves creating a new class based on the standard class and then writing code to create the control at run time. This is basically called superclassing.
For the majority of applications that you will ever write, subclassing is used more than superclassing. For most of us, you will probably never find a need to resort to superclassing.
... to answer your question, Roger has posted exactly what I would have said. You can call EnumWindows from within the Form's WM_CREATE message handler. You can also use control arrays or simply track the handles in global arrays based on the control's HWND's (refer to the F4 popup list). I expect that you are not creating controls at runtime so you should know what controls you need to deal with.
Here is the code being used in WSA, may be it could help you to deal
with most of the common controls based on their class names.
FUNCTION EnumChildProc(BYVAL hWnd&, BYVAL lParam AS LONG) AS LONG
LOCAL bt AS SKALL
LOCAL rc AS RECT
LOCAL cs AS COLORSCHEME
LOCAL pt AS POINTAPI
LOCAL zChildClass AS ASCIIZ * 32
IF GetClassName(hWnd&, zChildClass, SIZEOF(zChildClass)) THEN
hParent& = GetParent(hWnd&)
ItemParent& = skItem(hParent&)
zChildClass = UCASE$(zChildClass)
MDICLIENT$ = "MDICLIENT"
IF INSTR(zChildClass, MDICLIENT$) THEN zChildClass = MDICLIENT$
' May I skin the control?
IF NOT skSkinActive(hWnd&) THEN FUNCTION = %TRUE: EXIT FUNCTION
SELECT CASE CONST$ zChildClass
CASE "EZGUI30_SHAPE_32" ' Shape control
FUNCTION = %TRUE: EXIT FUNCTION
CASE "EZGUI30_DRAGHANDLES_32" ' Drag handles
FUNCTION = %TRUE: EXIT FUNCTION
CASE "EZGUI30_MASKEDIT32" ' Masked Edit
FUNCTION = %TRUE: EXIT FUNCTION
CASE "EZGUI30_MCI_32" ' MCI control
FUNCTION = %TRUE: EXIT FUNCTION
CASE "EZGUI30_TURTLE_32" ' Turtle control
FUNCTION = %TRUE: EXIT FUNCTION
CASE "EZGUI_CANVAS_32" ' Canvas control
FUNCTION = %TRUE: EXIT FUNCTION
CASE "EZGUI_MDICLIENT_32" ' MDI Client control
FUNCTION = %TRUE: EXIT FUNCTION
CASE "MDICLIENT"
IF GetParent(hParent&) = 0 THEN Win(ItemParent&).hMdiClient = hWnd&
CALL DeleteObject(SetClassLong (hWnd&, %GCL_HBRBACKGROUND, CreateSolidBrush(skGetSysColor(%SKCOLOR_INACTIVECAPTION))))
' Should we handle this big mess
CALL skMonitorCtrl(hWnd&, %CTRL_MDICLIENT)
CASE "TOOLBARWINDOW32"
IF GetParent(hParent&) = 0 THEN
CALL skMonitorCtrl(hWnd&, %CTRL_TOOLBAR)
cs.dwSize = SIZEOF(COLORSCHEME)
cs.clrBtnHighlight = skGetSysColor(%SKCOLOR_3DRIGHTBOTTOM)
cs.clrBtnShadow = skGetSysColor(%SKCOLOR_3DLEFTTOP)
CALL SendMessage(hWnd&, %TB_SETCOLORSCHEME, 0, BYVAL VARPTR(cs))
ELSE
CALL skMonitorCtrl(hWnd&, %CTRL_TOOLBAR)
cs.dwSize = SIZEOF(COLORSCHEME)
cs.clrBtnHighlight = skGetSysColor(%SKCOLOR_3DRIGHTBOTTOM)
cs.clrBtnShadow = skGetSysColor(%SKCOLOR_3DLEFTTOP)
CALL SendMessage(hWnd&, %TB_SETCOLORSCHEME, 0, BYVAL VARPTR(cs))
CALL DeleteObject(SetClassLong (hWnd&, %GCL_HBRBACKGROUND, BYVAL %NULL))
CALL SetWindowLong(hWnd&, %GWL_EXSTYLE, GetWindowLong(hWnd&, %GWL_EXSTYLE) OR %WS_EX_TRANSPARENT)
Child(skChild(hWnd&)).paintflag = %TRUE
END IF
CASE "MSCTLS_STATUSBAR32"
CALL skMonitorCtrl(hWnd&, %CTRL_STATUS)
CALL SetWindowLong(hWnd&, %GWL_EXSTYLE, GetWindowLong(hWnd&, %GWL_EXSTYLE) OR %WS_EX_TRANSPARENT)
IF ItemParent& THEN Win(ItemParent&).hStatus = hWnd&
CASE "BUTTON"
WasStyle& = GetWindowLong(hWnd&, %GWL_STYLE)
IF (WasStyle& AND %BS_GROUPBOX) = %BS_GROUPBOX THEN
CALL GetClientRect(hWnd&, rc)
CALL skMonitorCtrl(hWnd&, %CTRL_GROUPBOX)
CALL SetRect(Child(skChild(hWnd&)).rc, 0, 0, rc.nRight, rc.nBottom)
CALL SetWindowLong(hWnd&, %GWL_EXSTYLE, GetWindowLong(hWnd&, %GWL_EXSTYLE) OR %WS_EX_TRANSPARENT)
ELSEIF (WasStyle& AND %BS_CHECKBOX) = %BS_CHECKBOX THEN
UseStyle& = %CTRL_CHECKBOX
IF (WasStyle& AND %BS_OWNERDRAW) = %BS_OWNERDRAW THEN
UseStyle& = UseStyle& + %CTRL_OWNERDRAWN
END IF
CALL skMonitorCtrl(hWnd&, UseStyle&)
ELSEIF (WasStyle& AND %BS_AUTOCHECKBOX) = %BS_AUTOCHECKBOX THEN
UseStyle& = %CTRL_CHECKBOX
IF (WasStyle& AND %BS_OWNERDRAW) = %BS_OWNERDRAW THEN
UseStyle& = UseStyle& + %CTRL_OWNERDRAWN
END IF
CALL skMonitorCtrl(hWnd&, UseStyle&)
ELSEIF (WasStyle& AND %BS_RADIOBUTTON) = %BS_RADIOBUTTON THEN
UseStyle& = %CTRL_RADIOBUTTON
IF (WasStyle& AND %BS_OWNERDRAW) = %BS_OWNERDRAW THEN
UseStyle& = UseStyle& + %CTRL_OWNERDRAWN
END IF
CALL skMonitorCtrl(hWnd&, UseStyle&)
ELSEIF (WasStyle& AND %BS_AUTORADIOBUTTON) = %BS_AUTORADIOBUTTON THEN
UseStyle& = %CTRL_RADIOBUTTON
IF (WasStyle& AND %BS_OWNERDRAW) = %BS_OWNERDRAW THEN
UseStyle& = UseStyle& + %CTRL_OWNERDRAWN
END IF
CALL skMonitorCtrl(hWnd&, UseStyle&)
ELSE
IF (WasStyle& AND %BS_OWNERDRAW) = %BS_OWNERDRAW THEN
CALL skMonitorCtrl(hWnd&, %CTRL_PUSBUTTON + %CTRL_OWNERDRAWN)
ELSEIF (WasStyle& AND %BS_ICON) = %BS_ICON THEN
CALL skMonitorCtrl(hWnd&, %CTRL_PUSBUTTON + %CTRL_OWNERDRAWN)
ELSEIF (WasStyle& AND %BS_BITMAP) = %BS_BITMAP THEN
CALL skMonitorCtrl(hWnd&, %CTRL_PUSBUTTON + %CTRL_OWNERDRAWN)
ELSE
CALL SetWindowLong(hWnd&, %GWL_EXSTYLE, GetWindowLong(hWnd&, %GWL_EXSTYLE) XOR %WS_EX_DLGMODALFRAME)
Label$ = skGetCTLText(hWnd&)
ID& = GetDlgCtrlID(hWnd&)
EnableMode& = IsWindowEnabled(hWnd&)
IF ID& >= %ID_DOCKOUT AND ID& <= %ID_CLOSE THEN ID& = 0
IF ID& THEN
CALL GetWindowRect(hWnd&, rc)
xBut& = rc.nLeft
yBut& = rc.nTop
ButWidth& = rc.nRight - rc.nLeft
ButHeight& = rc.nBottom - rc.nTop
CALL SetWindowLong(hWnd&, %GWL_STYLE, WasStyle& OR %BS_OWNERDRAW)
bt.Button = 1
UseFont& = SendMessage(hWnd&, %WM_GETFONT, 0, 0): IF UseFont& = %NULL THEN UseFont& = skDefaultFont
CALL skDrawBut3D(hWnd&, Label$, UseFont&, ButWidth&, ButHeight&, bt)
CALL skMonitorCtrl(hWnd&, %CTRL_PUSBUTTON)
END IF
END IF
END IF
CASE "SYSTABCONTROL32"
CALL skMonitorCtrl(hWnd&, %CTRL_TAB)
CALL DeleteObject(SetClassLong (hWnd&, %GCL_HBRBACKGROUND, GetSysColor(%COLOR_3DFACE)))
CALL GetWindowRect(hWnd&, rc)
xOffset& = rc.nLeft: yOffset& = rc.nTop
XX& = rc.nRight - rc.nLeft: YY& = rc.nBottom - rc.nTop
CALL SendMessage(hWnd&, %TCM_ADJUSTRECT, %FALSE, BYVAL VARPTR(rc))
hRgnClip& = CreateRectRgn(0, 0, XX&, YY&)
xOffset& = rc.nLeft - xOffset&: yOffset& = rc.nTop - yOffset&
XX& = rc.nRight - rc.nLeft: YY& = rc.nBottom - rc.nTop
hRgn& = CreateRectRgn(xOffset&, yOffset&, xOffset& + XX&, yOffset& + YY&)
CALL CombineRgn(hRgnClip&, hRgnClip&, hRgn&, %RGN_DIFF)
CALL skDeleteObject(hRgn&)
CALL SetWindowRgn(hWnd&, hRgnClip&, %TRUE)
CASE "#32770"
CALL skMonitorCtrl(hWnd&, %CTRL_DIALOG)
CASE "STATIC"
CALL skMonitorCtrl(hWnd&, %CTRL_STATIC)
IF SendMessage(hWnd&, %WM_GETFONT, 0, 0) = %NULL THEN ' Bernard
CALL PostMessage(hWnd&, %WM_SETFONT, skDefaultFont, 0)
END IF
CASE "SYSTREEVIEW32"
CALL skMonitorCtrl(hWnd&, %CTRL_SYSTREEVIEW)
UseColor& = skGetSysColor(%SKCOLOR_CAPTIONTEXT)
' Check if UseColor& doesn't conflicts with the &hFFFFFF transparent background
IF UseColor& = &hFFFFFF THEN UseColor& = RGB(250,250,250) ' RGB(255,255,254)
CALL SendMessage(hWnd&, %TVM_SETBKCOLOR, 0, &hFFFFFF)
CALL SendMessage(hWnd&, %TVM_SETTEXTCOLOR, 0, UseColor&)
CALL SendMessage(hWnd&, %TVM_SETLINECOLOR, 0, UseColor&)
CASE "LISTBOX"
WasStyle& = GetWindowLong(hWnd&, %GWL_STYLE)
IF (WasStyle& AND %LBS_HASSTRINGS) THEN
CALL skMonitorCtrl(hWnd&, %CTRL_LISTBOX)
END IF
CASE "MSCTLS_TRACKBAR32"
CALL skMonitorCtrl(hWnd&, %CTRL_TRACKBAR)
CASE "SYSLISTVIEW32"
CALL skMonitorCtrl(hWnd&, %CTRL_LISTVIEW)
CALL SendMessage(hWnd&, %LVM_SETBKCOLOR, 0, skGetSysColor(%SKCOLOR_INACTIVECAPTION))
CALL SendMessage(hWnd&, %LVM_SETTEXTCOLOR, 0, skGetSysColor(%SKCOLOR_CAPTIONTEXT))
CALL SendMessage(hWnd&, %LVM_SETTEXTBKCOLOR, 0, skGetSysColor(%SKCOLOR_INACTIVECAPTION))
CASE "SYSHEADER32"
LOCAL pHD AS HD_ITEM
HeaderCount& = SendMessage(hWnd&, %HDM_GETITEMCOUNT, 0, 0)
IF HeaderCount& THEN ' Check if we can skin it or not
DoIt& = -1
FOR K& = 0 TO HeaderCount& - 1
pHD.Mask = %HDI_FORMAT
CALL SendMessage(hWnd&, %HDM_GETITEM, K&, VARPTR(pHD))
IF (pHD.fmt AND %HDF_OWNERDRAW) = %HDF_OWNERDRAW THEN DoIt& = 0: EXIT FOR
IF (pHD.fmt AND %HDF_BITMAP) = %HDF_BITMAP THEN DoIt& = 0: EXIT FOR
IF (pHD.fmt AND %HDF_BITMAP_ON_RIGHT) = %HDF_BITMAP_ON_RIGHT THEN DoIt& = 0: EXIT FOR
IF (pHD.fmt AND %HDF_IMAGE) = %HDF_IMAGE THEN DoIt& = 0: EXIT FOR
NEXT
IF DoIt& THEN CALL skMonitorCtrl(hWnd&, %CTRL_SYSHEADER)
END IF
CASE "RICHEDIT"
CALL skMonitorCtrl(hWnd&, %CTRL_RICHEDIT)
CASE ELSE
CALL skMonitorCtrl(hWnd&, %CTRL_UNDEFINED)
END SELECT
END IF
FUNCTION = %TRUE ' continue enumeration of children...
END FUNCTION