如何解决如何在选项卡控制区域内添加控件?
如何获取选项卡控制区域坐标,然后在该区域添加按钮?我不知道我应该使用哪一个 TabCtrl_GetItemRect()、GetWindowRect() 或其他东西,因为我似乎没有得到我想要的坐标,这是选项卡控制区域,我可以在那里把按钮。它目前位于远离选项卡控件白色区域的位置,我想将它们放置在那里,如下图所示。将它们放在此选项卡控件中的正确方法是什么?
处理这个的函数是这样的:
void CreateButtons(HWND hwnd)
{
RECT rt = {0};
//TabCtrl_GetItemRect(hTab,&rt);
GetwindowRect(hTab,&rt);
//GetClientRect(hTab,&rt);
/*
wchar_t buffer[256] = {0};
wsprintf(buffer,L"top = %d,bottom = %d,left = %d,right = %d",rt.top,rt.bottom,rt.left,rt.right);
MessageBox(NULL,buffer,L"",MB_OK);
*/
int id = 4;
static const wchar_t *title[] = { L"Button A",L"Button B",L"Button C",L"Button D",L"Button E",L"Button F",L"Button G",L"Button 001",L"Button 002",L"Button 003",L"Button 004" };
const int nMaxButtonPerRow = 3;
const int cx_margin = 10;
const int cy_bottomMarge = 10;
const int cy_breakSize = 25;
int cx_initPos = (int)rt.left;
int cx = cx_initPos;
int cy = 50;
const int width = 80;
const int height = 25;
for(int i = 0; i < sizeof(title)/sizeof(title[0]); ++i)
{
if(i != 0 && (i % nMaxButtonPerRow) == 0) {
cy += cy_breakSize + cy_bottomMarge;
cx = cx_initPos;
}
CreateWindow(L"button",title[i],WS_VISIBLE | WS_CHILD | WS_TABSTOP,cx,cy,width,height,hwnd,(HMENU) id++,NULL,NULL);
cx += width + cx_margin;
}
}
完整代码:
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Comctl32.lib")
#pragma comment(lib,"Gdi32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <Commctrl.h>
#include <crtdbg.h>
#include <strsafe.h>
#include <string.h>
#include <assert.h>
#ifdef UNICODE
#define STRSPLIT wcsrchr
#else
#define STRSPLIT strrchr
#endif
#define __FILENAME__ (STRSPLIT(TEXT(__FILE__),'/') ? STRSPLIT(TEXT(__FILE__),'/') + 1 : TEXT(__FILE__))
#define NAMEOF(s) TEXT(#s)
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
LRESULT CALLBACK WndProc(HWND,UINT,WParaM,LParaM);
LRESULT CALLBACK CreateTabProc(HWND,LParaM);
void ErrorExit(LPWSTR lpszFunction,int line,LPWSTR filename);
void InitComControls();
void ErrorExit(LPWSTR lpszFunction,LPWSTR filename);
DWORD ShowLastError(LPWSTR lpszFunction,LPWSTR filename);
void InitComControls();
void CreateTab(HWND hwnd);
void InsertTabItem(HWND tabHwnd,UINT id,LPWSTR text);
void CreateButtons(HWND hwnd);
HINSTANCE ghInstance;
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;
wc.hCursor = LoadCursor(0,IDC_ARROW);
InitComControls();
if(!RegisterClass(&wc)) {
ErrorExit(NAMEOF(RegisterClass),__LINE__,__FILENAME__);
}
int width = 500;
int height = 350;
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
int screenHeight = GetSystemMetrics(SM_CYSCREEN);
int cx = (screenWidth - width) / 2;
int cy = (screenHeight - height) / 2;
hwnd = CreateWindowW(wc.lpszClassName,L"Window",WS_OVERLAPPEDWINDOW | WS_VISIBLE,hInstance,NULL);
ghInstance = hInstance;
while (GetMessage(&msg,0))
{
if (!IsDialogMessage(hwnd,&msg))
{
TranslateMessage(&msg);
dispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WParaM wParam,LParaM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateWindowW(L"Static",L"This is label 1...",50,10,130,25,(HMENU) 18,NULL);
CreateWindowW(L"Static",L"This is label 2...",40,(HMENU) 19,NULL);
CreateTab(hwnd);
CreateButtons(hwnd);
//ChangetoDefaultFont(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
void CreateTab(HWND hwnd)
{
hTab =
CreateWindow(WC_TABCONTROLW,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_TABSTOP | WS_EX_CONTROLPARENT,80,400,250,(HMENU) 1,NULL);
InsertTabItem(hTab,2,L"Tab 1");
InsertTabItem(hTab,3,L"Tab b");
}
void CreateButtons(HWND hwnd)
{
RECT rt = {0};
//TabCtrl_GetItemRect(hTab,NULL);
cx += width + cx_margin;
}
}
void InsertTabItem(HWND tabHwnd,LPWSTR text)
{
TCITEMW tci = {0};
tci.mask = TCIF_TEXT;
tci.pszText = text;
tci.cchTextMax = lstrlenW(text);
SendMessage(tabHwnd,TCM_INSERTITEMW,id,(LParaM) &tci);
}
void InitComControls()
{
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
}
void ErrorExit(LPWSTR lpszFunction,LPWSTR filename)
{
DWORD dw = ShowLastError(lpszFunction,line,filename);
ExitProcess(dw);
}
DWORD ShowLastError(LPWSTR lpszFunction,LPWSTR filename)
{
#define MAX_DIGITS 16
DWORD dw = GetLastError();
LPVOID lpMsgBuf;
LPVOID lpdisplayBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYstem |
FORMAT_MESSAGE_IGnorE_INSERTS,dw,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,NULL
);
lpdisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT,(lstrlen((LPCTSTR)lpMsgBuf) +
lstrlen((LPCTSTR)lpszFunction) + 40 +
(line > 0 ? MAX_DIGITS : 0) +
(filename != NULL ? lstrlen(filename) : 0)) *
sizeof(TCHAR)
);
StringCchPrintf((LPTSTR)lpdisplayBuf,LocalSize(lpdisplayBuf) / sizeof(TCHAR),TEXT("%s Failed with %d: %s"),lpszFunction,lpMsgBuf
);
MessageBox(NULL,(LPCTSTR)lpdisplayBuf,TEXT("Error"),MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpdisplayBuf);
return dw;
}
更新 1: 使用 GetwindowRect()
和 MapWindowPoints()
设法做到了这一点。我错过了前一个。见 this 帖子。它获得了正确的选项卡控件坐标,但还没有获得控件应该打开的显示区域(白色区域)。我怎样才能得到这个白色区域的坐标?如果我设法获得选项卡按钮(由 TCM_INSERTITEM
消息插入的按钮)所在的窗口区域大小,也可以工作(不确定是否非常优雅)在设置 cx_initPos
时会跳过它们价值。
最新代码:
void CreateButtons(HWND hwnd)
{
RECT rt = GetLocalCoordinates(hTab);
int id = 4;
static const wchar_t *title[] = { L"Button A",L"Button 004" };
const int nMaxButtonPerRow = 3;
const int cx_margin = 10;
const int cy_bottomMarge = 10;
const int cy_breakSize = 25;
int cx_initPos = rt.left;
int cx = cx_initPos;
int cy = rt.top;
const int width = 80;
const int height = 25;
for(int i = 0; i < sizeof(title)/sizeof(title[0]); ++i)
{
if(i != 0 && (i % nMaxButtonPerRow) == 0) {
cy += cy_breakSize + cy_bottomMarge;
cx = cx_initPos;
}
CreateWindow(L"button",NULL);
cx += width + cx_margin;
}
}
RECT GetLocalCoordinates(HWND hWnd)
{
RECT Rect;
GetwindowRect(hWnd,&Rect);
MapWindowPoints(HWND_DESKTOP,GetParent(hWnd),(LPPOINT) &Rect,2);
return Rect;
}
现在的样子:
解决方法
如果需要在tab控件中添加按钮,应该传递hTab
作为按钮的父类:
CreateButtons(hTab);
x
类型:整数
窗口的初始水平位置。对于重叠或 弹出窗口,x参数是初始x坐标 窗口的左上角,以屏幕坐标表示。对于子窗口, x 是相对窗口左上角的 x 坐标 到父窗口客户区的左上角。如果这 参数设置为CW_USEDEFAULT,系统选择默认 窗口左上角的位置并忽略 y 范围。 CW_USEDEFAULT 仅对重叠窗口有效;如果它 为弹出窗口或子窗口指定,x 和 y 参数是 设置为零。
所以设置的坐标是相对于父窗口的左上角。不需要通过hTab
获取GetWindowRect
的位置信息,而是应该像下面的代码一样传递相对tab控件的位置:
int cx_initPos = 10;
int cx = cx_initPos;
它对我有用:
补充:如果需要针对不同的标签页进行调整,可以参考这个thread。
编辑:
您可以尝试在 TabCtrl_AdjustRect(hTab,FALSE,&rt);
后添加 RECT rt = GetLocalCoordinates(hTab);
:
RECT rt;
rt = GetLocalCoordinates(hTab);
TabCtrl_AdjustRect(hTab,&rt);
这是你想要的结果吗:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。