问题描述
我正在学习 WINAPI,我读到 C# 的 TabControl 控件没有儿童控件,因此您必须自己创建元素并显示/隐藏。我读到它可以通过在选项卡页区域内绘制一个对话框来完成,所以我去创建一个无边框对话框作为选项卡控件的子项,使其具有像 C# 一样的效果。但我还是做不到。我的对话框是浮动的,而不是选项卡控件的子控件。我不知道要在标签页中设置它,我尝试将 hWndParent
设置为标签控件的 HWND 和 WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT
中的 dwExStyle
标志,但仍然浮动在标签控件上。欢迎使用不同的方法来解决这个问题。我正在创建这样的选项卡控件:
void AddTabControl(HWND hwnd)
{
hTab = CreateWindowW(WC_TABCONTROLW,NULL,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_TABSTOP,30,250,hwnd,(HMENU) 9,NULL);
InsertTabItem(hTab,10,L"A");
InsertTabItem(hTab,11,L"B");
}
void InsertTabItem(HWND tabHwnd,UINT id,LPWSTR text)
{
TCITEMW tci = {0};
tci.mask = TCIF_TEXT;
tci.pszText = text;
tci.cchTextMax = lstrlenW(text);
if(SendMessage(tabHwnd,TCM_INSERTITEMW,id,(LParaM) &tci) == -1) {
MessageBox(NULL,L"Couldn't create the new tab page",L"tab errror",MB_OK | MB_ICONERROR);
}
}
还有这样的对话框:
void CreateDialogBox(HWND hwnd)
{
CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT,// WS_EX_TOOLWINDOW to hide window from ALT+TAB
L"DialogClass",L"Dialog Box",WS_VISIBLE | WS_POPUP | WS_SYSMENU,100,400,150,hTab,ghInstance,NULL
);
}
结果是:
预期结果(由 C# 制作,仅作为示例,忽略颜色差异,我稍后会解决此问题):
完整代码如下:
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Comctl32.lib")
#define UNICODE
#include <windows.h>
#include <Commctrl.h>
#include <strsafe.h>
LRESULT CALLBACK WndProc(HWND,UINT,WParaM,LParaM);
LRESULT CALLBACK DialogProc(HWND,LParaM);
void CreateDialogBox(HWND);
void RegisterDialogClass(HWND);
void AddTabControl(HWND hwnd);
void InsertTabItem(HWND tabHwnd,LPWSTR text);
HINSTANCE ghInstance;
HWND mainWindow;
HWND hTab;
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PWSTR pCmdLine,int nCmdshow) {
MSG msg = {0};
HWND hwnd;
WNDCLASSW wc = {0};
wc.lpszClassName = L"Window";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
RegisterClassW(&wc);
hwnd = CreateWindowW(wc.lpszClassName,L"Window",WS_OVERLAPPEDWINDOW | WS_VISIBLE,500,350,hInstance,NULL);
mainWindow = hwnd;
ghInstance = hInstance;
while( GetMessage(&msg,0)) {
dispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WParaM wParam,LParaM lParam)
{
switch(msg)
{
case WM_CREATE:
RegisterDialogClass(hwnd);
AddTabControl(hwnd);
CreateDialogBox(hwnd);
break;
case WM_COMMAND:
CreateDialogBox(hwnd);
break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProcW(hwnd,msg,wParam,lParam);
}
LRESULT CALLBACK DialogProc(HWND hwnd,LParaM lParam)
{
switch(msg) {
case WM_CREATE:
CreateWindowW(L"button",L"A",WS_VISIBLE | WS_CHILD,50,80,25,(HMENU) 1,NULL);
CreateWindowW(L"button",L"B",(HMENU) 2,NULL);
CreateWindowW(L"button",L"C",(HMENU) 3,NULL);
break;
case WM_COMMAND:
DestroyWindow(hwnd);
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
}
return (DefWindowProcW(hwnd,lParam));
}
void RegisterDialogClass(HWND hwnd)
{
WNDCLASSEXW wc = {0};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.lpfnWndProc = (WNDPROC) DialogProc;
wc.hInstance = ghInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpszClassName = L"DialogClass";
RegisterClassExW(&wc);
}
void CreateDialogBox(HWND hwnd)
{
CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT,NULL
);
}
void AddTabControl(HWND hwnd)
{
hTab = CreateWindowW(WC_TABCONTROLW,MB_OK | MB_ICONERROR);
}
}
解决方法
当您创建对话框控件时,您缺少 WS_CHILD
样式并添加了 WS_POPUP
样式,这导致您生成的对话框浮动。
您只需将其修改为WS_CHILD
样式,并适当修改控件的大小即可达到您想要的效果。
void CreateDialogBox(HWND hwnd)
{
CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT,// WS_EX_TOOLWINDOW to hide window from ALT+TAB
L"DialogClass",L"Dialog Box",WS_VISIBLE | WS_SYSMENU | WS_CHILD,10,30,350,150,hTab,NULL,ghInstance,NULL
);
}
void AddTabControl(HWND hwnd)
{
hTab = CreateWindowW(WC_TABCONTROLW,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_TABSTOP,400,250,hwnd,(HMENU)9,NULL);
InsertTabItem(hTab,L"A");
InsertTabItem(hTab,11,L"B");
}
它是这样工作的: