基于对话框的选项卡控件上的 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),我想我错过了什么。

我看到这里有两个问题。

  1. 在资源中,将DS_CONTROL位添加到IDD_DLG_PAGE1IDD_DLG_PAGE2

  2. 在代码中,在您的 WM_INITDIALOG 处理程序中,CreateDialog 调用表示您的 child 对话框已创建 children of hTabCtrlMain.改为 hWnd 的 children。