How to navigate with TAB to an edit control in a rebar control?

Started by japheth, January 08, 2011, 04:30:18 PM

Previous topic - Next topic

japheth

How to navigate with TAB to an edit control in a rebar control?

My sample - which uses a modeless dialog - doesn't "work":


.486
.model flat, stdcall
option casemap :none

include windows.inc

includelib kernel32.lib
includelib user32.lib
includelib comctl32.lib

IDC_REBAR1    equ 2
IDC_EDIT1     equ 3
IDC_EDIT2     equ 4
IDC_EDIT3     equ 5

CStr macro y:vararg
local sym,xxx
.const
sym db y,0
.code
exitm <offset sym>
endm

.data

g_hInstance HINSTANCE 0
g_hwndMain HWND 0
g_hwndRebar1 HWND 0
g_hwndEdit1 HWND 0
g_hwndEdit2 HWND 0
g_hwndEdit3 HWND 0

.code

OnSize proc uses ebx hWnd:HWND, wParam:WPARAM, lParam:LPARAM

LOCAL rect:RECT

mov eax,wParam
.if (eax == SIZE_RESTORED || eax == SIZE_MAXIMIZED)

invoke GetClientRect, hWnd, addr rect

invoke SetWindowPos, g_hwndRebar1, NULL, 0, 0,
rect.right, 24, SWP_NOZORDER or SWP_NOACTIVATE

invoke SetWindowPos, g_hwndEdit2, NULL, 0, 32,
rect.right, 24, SWP_NOZORDER or SWP_NOACTIVATE

invoke SetWindowPos, g_hwndEdit3, NULL, 0, 64,
rect.right, 24, SWP_NOZORDER or SWP_NOACTIVATE

.endif
ret
align 4

OnSize endp

;*** the main window proc

DlgProc proc hWnd:HWND, uMsg:DWORD, wParam:WPARAM, lParam:LPARAM

mov eax,uMsg
.if (eax == WM_INITDIALOG)
xor eax, eax
.elseif (eax == WM_CLOSE)
invoke DestroyWindow, hWnd
.elseif (eax == WM_DESTROY)
invoke PostQuitMessage,NULL
.elseif (eax == WM_SIZE)
invoke OnSize, hWnd, wParam, lParam
mov eax, 1
.elseif (eax == WM_COMMAND)
.if ( wParam == IDCANCEL )
invoke PostMessage, hWnd, WM_CLOSE, 0, 0
.endif
mov eax, 1
.else
xor eax, eax
.endif
ret
align 4

DlgProc endp

WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, lpszCmdLine:LPSTR, iCmdShow:dword

LOCAL ccsex:INITCOMMONCONTROLSEX
LOCAL msg:MSG
LOCAL rbbi:REBARBANDINFO

mov ccsex.dwSize, sizeof INITCOMMONCONTROLSEX
mov ccsex.dwICC, ICC_BAR_CLASSES
invoke InitCommonControlsEx, addr ccsex

;--- create modeless dialog

invoke CreateDialogParam, hInst, 1, NULL, DlgProc, 0
mov g_hwndMain, eax
.if (!eax)
invoke MessageBox, 0, CStr("CreateDialogParam failed"), 0, MB_OK
ret
.endif
invoke GetDlgItem, g_hwndMain, IDC_REBAR1
mov g_hwndRebar1, eax
invoke GetDlgItem, g_hwndMain, IDC_EDIT1
mov g_hwndEdit1, eax
invoke GetDlgItem, g_hwndMain, IDC_EDIT2
mov g_hwndEdit2, eax
invoke GetDlgItem, g_hwndMain, IDC_EDIT3
mov g_hwndEdit3, eax

;--- place first edit into rebar

mov rbbi.cbSize,SIZEOF REBARBANDINFO
mov rbbi.fMask,RBBIM_CHILD or RBBIM_SIZE or RBBIM_STYLE or RBBIM_CHILDSIZE or RBBIM_TEXT or RBBIM_ID
mov rbbi.lpText, CStr("rebar1")
mov eax, g_hwndEdit1
mov rbbi.hwndChild,eax
mov rbbi.fStyle, RBBS_GRIPPERALWAYS + RBBS_CHILDEDGE
mov rbbi.cx_,100
mov rbbi.cxMinChild,100
mov rbbi.cyChild,24
mov rbbi.cyMinChild,24
mov rbbi.wID,IDC_EDIT1
invoke SendMessage,g_hwndRebar1, RB_INSERTBAND,-1,addr rbbi

invoke ShowWindow, g_hwndMain, SW_NORMAL

.while (1)
invoke GetMessage,ADDR msg,NULL,0,0
.break .if (eax == 0)
invoke IsDialogMessage, g_hwndMain, ADDR msg
.continue .if eax
invoke TranslateMessage, ADDR msg
invoke DispatchMessage,  ADDR msg
.endw
exit:
mov eax, msg.wParam
ret
align 4

WinMain endp


start proc public

invoke GetModuleHandle, NULL
mov g_hInstance, eax

invoke WinMain, g_hInstance, 0, NULL, 0

invoke ExitProcess,eax

start endp

end start


the focus is placed onto the second edit control.
Pressing TAB switches between EDIT2 and EDIT3 control, EDIT1 is never reached.

Here's the resource file

#define IDC_REBAR1 2
#define IDC_EDIT1  3
#define IDC_EDIT2  4
#define IDC_EDIT3  5
#include <resource.h>

1 DIALOGEX 0, 0, 200, 100
STYLE DS_CENTER | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "rebar test"
BEGIN
    CONTROL         "Rebar1",IDC_REBAR1,"ReBarWindow32",RBS_BANDBORDERS | WS_TABSTOP,
                    0,0,200, 16, WS_EX_CLIENTEDGE
    EDITTEXT        IDC_EDIT1,0, 0,200,16, WS_TABSTOP | ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT2,0,20,200,16, WS_TABSTOP | ES_AUTOHSCROLL
    EDITTEXT        IDC_EDIT3,0,40,200,16, WS_TABSTOP | ES_AUTOHSCROLL
END



Removing WS_TABSTOP from the rebar doesn't help.


jj2007

\masm32\include\resource.h(1224) : warning RC4005: 'IDC_EDIT1' : redefinition
error A2006:undefined symbol : cx_ for mov rbbi.cx_,100

Apart from these minor problems, it works perfectly with the tab key...


japheth

Quote from: jj2007 on January 08, 2011, 05:25:40 PM
\masm32\include\resource.h(1224) : warning RC4005: 'IDC_EDIT1' : redefinition
error A2006:undefined symbol : cx_ for mov rbbi.cx_,100

I forgot to mention that I didn't use Masm32.

Quote
Apart from these minor problems, it works perfectly with the tab key...

Thanks for your efforts! I tried your exe, and it - at first glance - does indeed work "better": the first edit is reached with TAB. However, the dialog looks strange:



And, worse, I get pretty much the same result if I "forget" to set the child HWND:


mov rbbi.lpText, CStr("rebar1")
mov eax, g_hwndEdit1
;;; mov rbbi.hwndChild,eax
mov rbbi.fStyle, RBBS_GRIPPERALWAYS + RBBS_CHILDEDGE


which results in the rebar control having no childs at all. I guess the redefinition "warning" which you got from the resource compiler cannot be ignored in this case.


jj2007

Quote from: japheth on January 08, 2011, 06:28:34 PM
I guess the redefinition "warning" which you got from the resource compiler cannot be ignored in this case.

Yes. Attached a modified versions with 5 edits, of which 2 are children. Both do not accept keyboard input. It is as if the WS_TABSTOP would redirect input to the 'static' part of the ReBar control...

japheth


I finally found the answer: the rebar control must be created with WS_EX_CONTROLPARENT.

Explanation: this flag makes function GetNextDlgTabItem() - which determines which control will be the "next" one - to scan the childs of the control.

http://msdn.microsoft.com/en-us/library/ms644995%28v=vs.85%29.aspx

MichaelW

AFAICT, at least under Windows 2000:

mov ccsex.dwICC, ICC_BAR_CLASSES

Should be:

mov ccsex.dwICC, ICC_COOL_CLASSES

Otherwise CreateDialogParam fails and GetLastError returns:

Cannot find window class.

And with this change, I can navigate between the edit controls with the tab key.

With the exception that once I navigate away from the first, I cannot return to it with the tab key.


eschew obfuscation