基于对话框的选项卡控件上的 C winapi 选项卡
C winapi tab on dialog based tabcontrol
我正在处理基于子对话框的 TabControl 对话框。
Tab 键在父对话框中运行良好,但永远不会将控件集中在子对话框中。
我创建了一个简单示例来重现该问题。
我在 Window 7 上工作,我使用 MinGW 作为编译器,使用 ResEdit/Notepad++ 作为资源编辑。有人可以帮助我吗?
C源文件"tabdlg.c":
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
HANDLE hInstance;
HWND hDlgMain;
HWND hDlgPage1;
HWND hDlgPage2;
HWND hTabCtrlMain;
BOOL CALLBACK DlgPage1Fn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
BOOL CALLBACK DlgPage2Fn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
BOOL CALLBACK DlgMainFn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg){
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_INITDIALOG:
{
hInstance=GetModuleHandle(NULL);
hDlgMain=hWnd;
TCITEM tcBtn;
hTabCtrlMain=GetDlgItem(hDlgMain,IDT_TAB_CTRL_MAIN);
memset(&tcBtn,0x0,sizeof(TCITEM));
tcBtn.mask = TCIF_TEXT;
tcBtn.pszText = "Page 1";
SendMessage(hTabCtrlMain, TCM_INSERTITEM, 0, (LPARAM)&tcBtn);
hDlgPage1=CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DLG_PAGE1), hTabCtrlMain, DlgPage1Fn);
tcBtn.pszText = "Page 2";
SendMessage(hTabCtrlMain, TCM_INSERTITEM, 1, (LPARAM)&tcBtn);
hDlgPage2=CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DLG_PAGE2), hTabCtrlMain, DlgPage2Fn);
ShowWindow(hDlgPage2, SW_HIDE);
}
return TRUE;
case WM_NOTIFY:
{
INT nSel;
UINT uNotify=((LPNMHDR)lParam)->code;
switch(uNotify){
case TCN_SELCHANGE:
nSel=SendMessage(hTabCtrlMain, TCM_GETCURSEL, 0, 0);
if (nSel==0){
ShowWindow(hDlgPage1, SW_SHOW);
ShowWindow(hDlgPage2, SW_HIDE);
}else{
ShowWindow(hDlgPage1, SW_HIDE);
ShowWindow(hDlgPage2, SW_SHOW);
}
break;
}
}
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DLG_MAIN), NULL, &DlgMainFn);
return 0;
}
资源包含文件 "resource.h" :
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDD_DLG_MAIN 103
#define IDD_DLG_PAGE1 105
#define IDD_DLG_PAGE2 107
#define IDB_BTN_PAGE1 40000
#define IDB_BTN_PAGE2 40000
#define IDE_EDIT_MAIN 40000
#define IDB_BTN_MAIN_B 40001
#define IDE_EDIT_PAGE2 40001
#define IDB_BTN_MAIN_A 40003
#define IDT_TAB_CTRL_MAIN 40004
资源文件"tabdlg.rc":
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DLG_MAIN DIALOG 0, 0, 327, 207
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Main Dialog"
FONT 8, "Ms Shell Dlg"
{
PUSHBUTTON "Main Button A", IDB_BTN_MAIN_A, 7, 7, 140, 14, 0, WS_EX_LEFT
PUSHBUTTON "Main Button B", IDB_BTN_MAIN_B, 175, 7, 145, 14, 0, WS_EX_LEFT
CONTROL "", IDT_TAB_CTRL_MAIN, WC_TABCONTROL, WS_TABSTOP, 7, 30, 313, 142, WS_EX_LEFT
EDITTEXT IDE_EDIT_MAIN, 7, 177, 313, 14, ES_AUTOHSCROLL, WS_EX_LEFT
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DLG_PAGE1 DIALOG 0, 20, 186, 95
STYLE DS_3DLOOK | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
FONT 8, "Ms Shell Dlg"
{
PUSHBUTTON "Page1 Button", IDB_BTN_PAGE1, 67, 37, 48, 14, 0, WS_EX_LEFT
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DLG_PAGE2 DIALOG 0, 20, 186, 95
STYLE DS_3DLOOK | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
FONT 8, "Ms Shell Dlg"
{
DEFPUSHBUTTON "Page2 Button", IDB_BTN_PAGE2, 67, 32, 48, 14, 0, WS_EX_LEFT
EDITTEXT IDE_EDIT_PAGE2, 72, 57, 40, 14, ES_AUTOHSCROLL, WS_EX_LEFT
}
简单的构建脚本 "make.bat" :
gcc -c tabdlg.c -o tabdlg.o
windres tabdlg.rc -O coff -o tabdlg.res
gcc tabdlg.o tabdlg.res -o tabdlg.exe -mwindows -lcomctl32
我尝试了不同的方法但没有成功(例如:DS_CONTROL 或 WS_EX_CONTROLPARENT),我想我错过了什么。
我看到这里有两个问题。
在资源中,将DS_CONTROL
位添加到IDD_DLG_PAGE1
和IDD_DLG_PAGE2
。
在代码中,在您的 WM_INITDIALOG
处理程序中,CreateDialog
调用表示您的 child 对话框已创建 children of hTabCtrlMain
.改为 hWnd
的 children。
我正在处理基于子对话框的 TabControl 对话框。 Tab 键在父对话框中运行良好,但永远不会将控件集中在子对话框中。
我创建了一个简单示例来重现该问题。 我在 Window 7 上工作,我使用 MinGW 作为编译器,使用 ResEdit/Notepad++ 作为资源编辑。有人可以帮助我吗?
C源文件"tabdlg.c":
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
HANDLE hInstance;
HWND hDlgMain;
HWND hDlgPage1;
HWND hDlgPage2;
HWND hTabCtrlMain;
BOOL CALLBACK DlgPage1Fn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
BOOL CALLBACK DlgPage2Fn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
BOOL CALLBACK DlgMainFn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg){
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
case WM_INITDIALOG:
{
hInstance=GetModuleHandle(NULL);
hDlgMain=hWnd;
TCITEM tcBtn;
hTabCtrlMain=GetDlgItem(hDlgMain,IDT_TAB_CTRL_MAIN);
memset(&tcBtn,0x0,sizeof(TCITEM));
tcBtn.mask = TCIF_TEXT;
tcBtn.pszText = "Page 1";
SendMessage(hTabCtrlMain, TCM_INSERTITEM, 0, (LPARAM)&tcBtn);
hDlgPage1=CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DLG_PAGE1), hTabCtrlMain, DlgPage1Fn);
tcBtn.pszText = "Page 2";
SendMessage(hTabCtrlMain, TCM_INSERTITEM, 1, (LPARAM)&tcBtn);
hDlgPage2=CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DLG_PAGE2), hTabCtrlMain, DlgPage2Fn);
ShowWindow(hDlgPage2, SW_HIDE);
}
return TRUE;
case WM_NOTIFY:
{
INT nSel;
UINT uNotify=((LPNMHDR)lParam)->code;
switch(uNotify){
case TCN_SELCHANGE:
nSel=SendMessage(hTabCtrlMain, TCM_GETCURSEL, 0, 0);
if (nSel==0){
ShowWindow(hDlgPage1, SW_SHOW);
ShowWindow(hDlgPage2, SW_HIDE);
}else{
ShowWindow(hDlgPage1, SW_HIDE);
ShowWindow(hDlgPage2, SW_SHOW);
}
break;
}
}
return TRUE;
}
return FALSE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DLG_MAIN), NULL, &DlgMainFn);
return 0;
}
资源包含文件 "resource.h" :
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDD_DLG_MAIN 103
#define IDD_DLG_PAGE1 105
#define IDD_DLG_PAGE2 107
#define IDB_BTN_PAGE1 40000
#define IDB_BTN_PAGE2 40000
#define IDE_EDIT_MAIN 40000
#define IDB_BTN_MAIN_B 40001
#define IDE_EDIT_PAGE2 40001
#define IDB_BTN_MAIN_A 40003
#define IDT_TAB_CTRL_MAIN 40004
资源文件"tabdlg.rc":
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DLG_MAIN DIALOG 0, 0, 327, 207
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Main Dialog"
FONT 8, "Ms Shell Dlg"
{
PUSHBUTTON "Main Button A", IDB_BTN_MAIN_A, 7, 7, 140, 14, 0, WS_EX_LEFT
PUSHBUTTON "Main Button B", IDB_BTN_MAIN_B, 175, 7, 145, 14, 0, WS_EX_LEFT
CONTROL "", IDT_TAB_CTRL_MAIN, WC_TABCONTROL, WS_TABSTOP, 7, 30, 313, 142, WS_EX_LEFT
EDITTEXT IDE_EDIT_MAIN, 7, 177, 313, 14, ES_AUTOHSCROLL, WS_EX_LEFT
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DLG_PAGE1 DIALOG 0, 20, 186, 95
STYLE DS_3DLOOK | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
FONT 8, "Ms Shell Dlg"
{
PUSHBUTTON "Page1 Button", IDB_BTN_PAGE1, 67, 37, 48, 14, 0, WS_EX_LEFT
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DLG_PAGE2 DIALOG 0, 20, 186, 95
STYLE DS_3DLOOK | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
FONT 8, "Ms Shell Dlg"
{
DEFPUSHBUTTON "Page2 Button", IDB_BTN_PAGE2, 67, 32, 48, 14, 0, WS_EX_LEFT
EDITTEXT IDE_EDIT_PAGE2, 72, 57, 40, 14, ES_AUTOHSCROLL, WS_EX_LEFT
}
简单的构建脚本 "make.bat" :
gcc -c tabdlg.c -o tabdlg.o
windres tabdlg.rc -O coff -o tabdlg.res
gcc tabdlg.o tabdlg.res -o tabdlg.exe -mwindows -lcomctl32
我尝试了不同的方法但没有成功(例如:DS_CONTROL 或 WS_EX_CONTROLPARENT),我想我错过了什么。
我看到这里有两个问题。
在资源中,将
DS_CONTROL
位添加到IDD_DLG_PAGE1
和IDD_DLG_PAGE2
。在代码中,在您的
WM_INITDIALOG
处理程序中,CreateDialog
调用表示您的 child 对话框已创建 children ofhTabCtrlMain
.改为hWnd
的 children。