// 创建TabCtrl控件
hTabCtrl = CreateWindowEx(0, TEXT("SysTabControl32"), NULL, WS_VISIBLE | WS_CHILD | TCS_TABS,
10, 10, 300, 200, hWnd, (HMENU)10001, hInstance, 0);
// 插入选项卡
TCITEM tcItem = { 0 };
tcItem.mask = TCIF_IMAGE | TCIF_TEXT;
tcItem.pszText = (LPTSTR)TEXT("Item1");
tcItem.iImage = 0;
SendMessage(hTabCtrl, TCM_INSERTITEM, 0, (LPARAM)&tcItem);
tcItem.pszText = (LPTSTR)TEXT("Item2");
SendMessage(hTabCtrl, TCM_INSERTITEM, 1, (LPARAM)&tcItem);
tcItem.pszText = (LPTSTR)TEXT("Item3");
SendMessage(hTabCtrl, TCM_INSERTITEM, 2, (LPARAM)&tcItem);
效果图片:
名称 |
说明 |
TCS_BOTTOM |
选项卡显示在底部 |
TCS_BUTTONS |
选项卡显示为按钮样式 |
TCS_FIXEDWIDTH |
所有选项卡宽度相同 |
TCS_FLATBUTTONS |
选项卡显示为缩进背景 |
TCS_FOCUSNEVER |
单击选项卡时不会接收输入焦点 |
TCS_FOCUSONBUTTONDOWN |
单击选项卡时接收输入焦点 |
TCS_FORCEICONLEFT |
图标在选项卡左边 |
TCS_FORCELABELLEFT |
标签显示在左边 |
TCS_HOTTRACK |
鼠标下的项会自动突出显示 |
TCS_MULTILINE |
多行显示选项卡 |
TCS_MULTISELECT |
按住Ctrl键选择多个选项卡 |
TCS_OWNERDRAWFIXED |
父窗口绘制选项卡 |
TCS_RAGGEDRIGHT |
不拉伸制表符以填充控件的整个宽度 |
TCS_RIGHT |
选项卡显示在右边和TCS_VERITCAL一起用有效 |
TCS_RIGHTJUSTIFY |
增加每个选项卡宽度,填充控件的整个宽度 |
TCS_SCROLLOPPOSITE |
选中选项卡时,其他选项卡滚动到控件对面 |
TCS_SINGLELINE |
只显示一行选项卡 |
TCS_TABS |
显示为选项卡样式 |
TCS_TOOLTIPS |
具有工具提示控件 |
TCS_VERTICAL |
选项卡显示在控件左侧,文本垂直显示,与TCS_MULTILINE一起才有效, |
消息ID |
说明 |
WPARAM |
LPARAM |
返回值 |
TCM_ADJUSTRECT |
计算控件显示区域 |
True(包含选项卡), False(不含选项卡) |
LPRECT |
VOID |
TCM_DELETEALLITEMS |
删除所有选项卡 |
0 |
0 |
BOOL |
TCM_DELETEITEM |
删除指定选项卡 |
nIndex |
0 |
BOOL |
TCM_DESELECTALL |
重置选项卡中的项目 |
True(重置除了选中项以外的选项卡,False重置所有选项卡 |
0 |
VOID |
TCM_GETCURFOCUS |
获得有焦点项的索引 |
0 |
0 |
INT |
TCM_GETCURSEL |
获得当前选定项的索引 |
0 |
0 |
INT |
TCM_GETEXTENDEDSTYLE |
获得控件的扩展样式 |
0 |
0 |
DWORD |
TCM_GETIMAGELIST |
获得控件关联的图像列表 |
0 |
0 |
HIMAGELIST |
TCM_GETITEM |
获得选项卡的信息 |
nIndex |
LPTCITEM |
BOOL |
TCM_GETITEMCOUNT |
获得选项卡个数 |
0 |
0 |
INT |
TCM_GETITEMRECT |
获得选项卡边界矩形 |
nIndex |
LPRECT |
BOOL |
TCM_GETROWCOUNT |
获得选项卡行数 |
0 |
0 |
INT |
TCM_GETTOOLTIPS |
获得提示工具句柄 |
0 |
0 |
HTOOLTIP |
TCM_HIGHLIGHITITEM |
设置突出显示选项卡 |
nIndex |
BOOL |
BOOL |
TCM_INSERTITEM |
插入新的选项卡 |
nIndex |
LPTCITEM |
INT |
TCM_REMOVEIMAGE |
从图像列表中删除图像 |
nIndex |
0 |
VOID |
TCM_SETCURFOCUS |
设置选项卡焦点项 |
nIndex |
0 |
VOID |
TCM_SETCURSEL |
设置当前选中的项 |
nIndex |
0 |
INT |
TCM_SETEXTENDEDSTYLE |
设置控件的扩展样式 |
0(DWORD) |
DOWRD(扩展样式组合) |
DWORD(原来的样式) |
TCM_SETIMAGELIST |
设置关联的图像列表 |
0 |
HIMAGELIST |
HIMAGELIST |
TCM_SETITEM |
设置选项卡信息 |
nIndex |
LPTCITEM |
BOOL |
TCM_SETITEMSIZE |
设置选项卡宽度 |
0 |
DWORD(W,H) |
DWORD(old) |
TCM_SETMINTABWIDTH |
设置选项卡最小宽度 |
0 |
最小宽度 |
Int |
TCM_SETPADDING |
设置图标和标签的间距 |
0 |
DWORD(X,Y) |
VOID |
TCM_SETTOOLTIPS |
设置提示工具 |
HTOOLTIP |
0 |
VOID |
TCM_SETUNICODEFROMAT |
设置控件使用的字符集 |
True=Unicode False=Ansi |
0 |
Int(原来的字符集) |
通过发送WM_NOTIFY通知父窗口消息
消息ID |
说明 |
NM_CLICK |
单击选项卡 |
NM_DBLCLK |
双击选项卡 |
NM_RCLICK |
鼠标右键单击选项卡 |
NM_RDBLCLK |
鼠标右键双击选项卡 |
NM_RELEASEDCAPTURE |
释放鼠标捕获 |
TCN_FOCUSCHANGE |
控件焦点更改消息 |
TCN_GETOBJECT |
对象拖动到选项卡上时的消息,要有(TCS_EX_REGISTERDROP样式) |
TCN_KEYDOWN |
键盘消息 |
TCN_SELCHANGE |
选项卡更改消息 |
TCN_SELCHANGING |
选项卡正在更改消息 |
在资源中添加两个模板对话框,对话框样式为: 边框为:Thin(细边框),样式:Child(子窗口)
保存两个模板对话框句柄为成员变量,m_dlg1,m_dlg2
在窗口初始的时候创建对话框
// 创建两个模板对话框 m_dlg1 = CreateDialog(hInstance,MAKEINTRESOURCE(IDD_FORMVIEW) ,hTabCtrl, lpDialogProc); m_dlg2 = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW1), hTabCtrl, lpDialogProc); // 计算TabCtrl控件的显示区域 RECT rc; GetClientRect(hTabCtrl, &rc); // 获得控件客服区大小 SendMessage(hTabCtrl, TCM_ADJUSTRECT, 0, (LPARAM)&rc); // 重新计算除了选项卡的显示区域 InflateRect(&rc, -2, -2); // 缩小区域 MoveWindow(m_dlg1, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); // 把对话框移动到显示区域 ShowWindow(m_dlg1, SW_SHOW); // 显示对话框 |
// 计算TabCtrl控件的显示区域 RECT rc; GetClientRect(hTabCtrl, &rc); // 获得控件客服区大小 SendMessage(hTabCtrl, TCM_ADJUSTRECT, 0, (LPARAM)&rc); // 重新计算除了选项卡的显示区域 |
创建一个显示对话框的句柄,用来保存当前选中项的附加数据中的句柄,m_hShowDlg
初始的时候m_hShowDlg=m_dlg1;
// 保存对话框句柄到选项卡的附加数据中 tcItem.mask = TCIF_PARAM; tcItem.lParam = (LPARAM)m_dlg1; SendMessage(hTabCtrl, TCM_SETITEM, 0, (LPARAM)&tcItem); tcItem.lParam = (LPARAM)m_dlg2; SendMessage(hTabCtrl, TCM_SETITEM, 1, (LPARAM)&tcItem); |
在父窗口WM_NOTIFY消息中
// 子控件通知消息 LRESULT OnNotify(HWND hWnd, WPARAM wParam, LPARAM lParam) { // 强制类型转换 LPNMHDR lpNmhdr = reinterpret_cast<LPNMHDR>(lParam); if (lpNmhdr->hwndFrom == hTabCtrl) { switch (lpNmhdr->code) { case TCN_SELCHANGE: { if (m_hShowDlg) { ShowWindow(m_hShowDlg, SW_HIDE); // 将原来的对话框隐藏 } // 获得当前选中项的索引 int nSel = SendMessage(hTabCtrl, TCM_GETCURSEL, 0, 0L); // 获得选中项附加数据保存的对话框句柄 TCITEM tcItem = { 0 }; tcItem.mask = TCIF_PARAM; SendMessage(hTabCtrl, TCM_GETITEM, nSel, (LPARAM)&tcItem); m_hShowDlg= (HWND)tcItem.lParam; // 显示选中项关联的对话框 if (m_hShowDlg) { ShowWindow(m_hShowDlg,SW_SHOW ); } break; } default: break; } } return 0; } |
选中第一个选项卡效果:
选中第二个选项卡效果:
#include "Win32_Template.h" #include "resource.h" #include HWND hTabCtrl; //HWND hTabCtr2; //HWND hTabCtr3; //HWND hTabCtr4; HWND m_dlg1, m_dlg2,m_hShowDlg; // 主窗口过程函数 static LRESULT CALLBACK AfxWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // 对话框过程函数 static INT_PTR CALLBACK lpDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); LRESULT OnNotify(HWND hWnd, WPARAM wParam, LPARAM lParam); LRESULT OnCreate(HWND hWnd,LPARAM lParam); // 主函数WinMain int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) { // 1.设置窗口类名 TCHAR clsName[] = TEXT("WndClassName"); // 2.设置窗口类结构体WNDCLASSEX ,共12项 WNDCLASSEX wcEx = { 0 }; { // 必填项 wcEx.cbSize = sizeof(WNDCLASSEX); wcEx.style = CS_VREDRAW | CS_HREDRAW; wcEx.hInstance = hInstance; wcEx.lpfnWndProc = AfxWindowProc; wcEx.lpszClassName = clsName; wcEx.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); // 可填项 wcEx.cbClsExtra = 0; wcEx.cbWndExtra = 0; wcEx.hCursor = LoadCursor(NULL, IDC_ARROW); wcEx.hIcon = LoadIcon(NULL, IDI_WINLOGO); wcEx.hIconSm = wcEx.hIcon; wcEx.lpszMenuName = nullptr; } // 3.注册窗口类 if (FALSE == RegisterClassEx(&wcEx)) { MessageBox(nullptr, TEXT("注册窗口类失败!"), TEXT("提示"), MB_OK); return -1; } // 4.创建窗口 HWND hMainWnd = CreateWindowEx(0, clsName, TEXT("Win32_Template窗口"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 500, NULL, NULL, hInstance, 0); // 5.显示/更新窗口 CenterWindow(hMainWnd, NULL); // 窗口居中显示 ShowWindow(hMainWnd, nShowCmd); UpdateWindow(hMainWnd); SetActiveWindow(hMainWnd); // 激活窗口 // 6.消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 退出程序 return (int)msg.wParam; } // 窗口回调函数 LRESULT CALLBACK AfxWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // 消息选择 switch (uMsg) { case WM_CREATE: // 窗口的创建 return OnCreate(hWnd, lParam); case WM_DESTROY: // 窗口销毁 PostQuitMessage(0); return 0; case WM_CLOSE: // 窗口关闭 return DestroyWindow(hWnd); case WM_COMMAND: // 命令消息 return OnCommand(hWnd, wParam, lParam); case WM_NOTIFY: // 子控件通知消息 return OnNotify(hWnd, wParam, lParam); default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } INT_PTR CALLBACK lpDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return 0; } // 按钮,菜单,加速键,命令消息,Edit控件通知消息 LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { return 0; } // 子控件通知消息 LRESULT OnNotify(HWND hWnd, WPARAM wParam, LPARAM lParam) { // 强制类型转换 LPNMHDR lpNmhdr = reinterpret_cast<LPNMHDR>(lParam); if (lpNmhdr->hwndFrom == hTabCtrl) { switch (lpNmhdr->code) { case TCN_SELCHANGE: { if (m_hShowDlg) { ShowWindow(m_hShowDlg, SW_HIDE); // 将原来的对话框隐藏 } int nSel = SendMessage(hTabCtrl, TCM_GETCURSEL, 0, 0L); // 获得当前选中项的索引 // 获得选中项附加数据保存的对话框句柄 TCITEM tcItem = { 0 }; tcItem.mask = TCIF_PARAM; SendMessage(hTabCtrl, TCM_GETITEM, nSel, (LPARAM)&tcItem); m_hShowDlg= (HWND)tcItem.lParam; // 显示选中项关联的对话框 if (m_hShowDlg) { ShowWindow(m_hShowDlg,SW_SHOW ); } break; } default: break; } } return 0; } // 创建窗口消息 LRESULT OnCreate(HWND hWnd, LPARAM lParam) { LPCREATESTRUCT lpCreate = reinterpret_cast<LPCREATESTRUCT>(lParam); HINSTANCE hInstance = lpCreate->hInstance; // 创建TabCtrl控件 hTabCtrl = CreateWindowEx(0, TEXT("SysTabControl32"), NULL, WS_VISIBLE | WS_CHILD | TCS_TABS, 10, 10, 300, 200, hWnd, (HMENU)10001, hInstance, 0); // 选项卡显示在底部 /*hTabCtr2 = CreateWindowEx(0, TEXT("SysTabControl32"), NULL, WS_VISIBLE | WS_CHILD | TCS_BOTTOM, 320, 10, 300, 200, hWnd, (HMENU)10002, hInstance, 0); // 选项卡显示在左侧 hTabCtr3 = CreateWindowEx(0, TEXT("SysTabControl32"), NULL, WS_VISIBLE | WS_CHILD | TCS_MULTILINE|TCS_VERTICAL, 10, 220, 300, 200, hWnd, (HMENU)10003, hInstance, 0); // 选项卡显示在右侧 hTabCtr4 = CreateWindowEx(0, TEXT("SysTabControl32"), NULL, WS_VISIBLE | WS_CHILD | TCS_VERTICAL | TCS_RIGHT, 320, 220, 300, 200, hWnd, (HMENU)10004, hInstance, 0);*/ // 插入选项卡 TCITEM tcItem = { 0 }; tcItem.mask = TCIF_IMAGE | TCIF_TEXT; tcItem.pszText = (LPTSTR)TEXT("Item1"); tcItem.iImage = 0; SendMessage(hTabCtrl, TCM_INSERTITEM, 0, (LPARAM)&tcItem); tcItem.pszText = (LPTSTR)TEXT("Item2"); SendMessage(hTabCtrl, TCM_INSERTITEM, 1, (LPARAM)&tcItem); tcItem.pszText = (LPTSTR)TEXT("Item3"); SendMessage(hTabCtrl, TCM_INSERTITEM, 2, (LPARAM)&tcItem);
// 创建两个模板对话框 m_dlg1 = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW), hTabCtrl, lpDialogProc); m_dlg2 = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW1), hTabCtrl, lpDialogProc); // 计算TabCtrl控件的显示区域 RECT rc; GetClientRect(hTabCtrl, &rc); // 获得控件客服区大小 SendMessage(hTabCtrl, TCM_ADJUSTRECT, 0, (LPARAM)&rc); // 重新计算除了选项卡的显示区域 InflateRect(&rc, -2, -2); // 缩小区域 MoveWindow(m_dlg1, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); // 把对话框移动到显示区域 MoveWindow(m_dlg2, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); m_hShowDlg = m_dlg1; ShowWindow(m_dlg1, SW_SHOW); // 显示第一个对话框 // 保存对话框句柄到选项卡的附加数据中 tcItem.mask = TCIF_PARAM; tcItem.lParam = (LPARAM)m_dlg1; SendMessage(hTabCtrl, TCM_SETITEM, 0, (LPARAM)&tcItem); tcItem.lParam = (LPARAM)m_dlg2; SendMessage(hTabCtrl, TCM_SETITEM, 1, (LPARAM)&tcItem); return 0; } |