windows编程中创建TabControl的问题

ZiSheng 2016-12-08 04:47:41

///////////////////////////////////////////
// ProgressDemo.cpp文件


#include <windows.h>
#include <commctrl.h>
#include "resource.h"
#define sz_Or_Ord WORD
#define titleLen 100
#define stringLen 100
#define C_PAGES 3
// 链接到comctl32.lib库
#pragma comment(lib,"comctl32.lib")

typedef struct {
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
sz_Or_Ord menu;
sz_Or_Ord windowClass;
WCHAR title[titleLen];
WORD pointsize;
WORD weight;
BYTE italic;
BYTE charset;
WCHAR typeface[stringLen];
} DLGTEMPLATEEX;

typedef struct tag_dlghdr {
HWND hwndTab; // tab control
HWND hwndDisplay; // current child dialog box
RECT rcDisplay; // display rectangle for the tab control
DLGTEMPLATEEX *apRes[C_PAGES];
} DLGHDR;

BOOL __stdcall ChildDialogProc(HWND, UINT, WPARAM, LPARAM);
BOOL __stdcall DlgProc(HWND, UINT, WPARAM, LPARAM);
HRESULT OnTabbedDialogInit(HWND hwndDlg);
DLGTEMPLATEEX* DoLockDlgRes(LPCTSTR lpszResName);
VOID OnSelChanged(HWND hwndDlg);

HINSTANCE g_hInst;

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
::InitCommonControls();
g_hInst = hInstance;
::DialogBoxParam(
hInstance, // 实例句柄
(LPCTSTR)IDD_MAIN, // 对话框资源ID号
NULL, // 父窗口句柄
DlgProc, // 消息处理函数
NULL); // 对话框初始化的值,在WM_INITDIALOG消息的lParam参数中取出

return 0;
}


BOOL __stdcall DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{
OnTabbedDialogInit(hDlg);
}
break;

case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:

break;
case IDCANCEL:
::EndDialog (hDlg, IDCANCEL);
break;
}
break;
}
return 0;
}

HRESULT OnTabbedDialogInit(HWND hwndDlg)
{
INITCOMMONCONTROLSEX iccex;
DWORD dwDlgBase = GetDialogBaseUnits();
int cxMargin = LOWORD(dwDlgBase) / 4;
int cyMargin = HIWORD(dwDlgBase) / 8;

TCITEM tie;
RECT rcTab;
HWND hwndButton;
RECT rcButton;
int i;

// Initialize common controls.
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&iccex);

// Allocate memory for the DLGHDR structure. Remember to
// free this memory before the dialog box is destroyed.
DLGHDR *pHdr = (DLGHDR *) LocalAlloc(LPTR, sizeof(DLGHDR));

// Save a pointer to the DLGHDR structure in the window
// data of the dialog box.
SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) pHdr);

// Create the tab control. Note that g_hInst is a global
// instance handle.
pHdr->hwndTab = CreateWindow(WC_TABCONTROL, "",WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,0,0,100,100,hwndDlg, NULL, g_hInst,NULL);
if (pHdr->hwndTab == NULL)
{
return HRESULT_FROM_WIN32(GetLastError());
}

// Add a tab for each of the three child dialog boxes.
tie.mask = TCIF_TEXT | TCIF_IMAGE;
tie.iImage = -1;
tie.pszText = "First";
TabCtrl_InsertItem(pHdr->hwndTab, 0, &tie);
tie.pszText = "Second";
TabCtrl_InsertItem(pHdr->hwndTab, 1, &tie);
tie.pszText = "Third";
TabCtrl_InsertItem(pHdr->hwndTab, 2, &tie);

// Lock the resources for the three child dialog boxes.
pHdr->apRes[0] = DoLockDlgRes(MAKEINTRESOURCE(IDD_FIRSTDLG));
pHdr->apRes[1] = DoLockDlgRes(MAKEINTRESOURCE(IDD_SECONDDLG));
pHdr->apRes[2] = DoLockDlgRes(MAKEINTRESOURCE(IDD_THIRDDLG));

// Determine a bounding rectangle that is large enough to
// contain the largest child dialog box.
SetRectEmpty(&rcTab);
for (i = 0; i < C_PAGES; i++)
{
if (pHdr->apRes[i]->cx > rcTab.right)
rcTab.right = pHdr->apRes[i]->cx;
if (pHdr->apRes[i]->cy > rcTab.bottom)
rcTab.bottom = pHdr->apRes[i]->cy;
}

// Map the rectangle from dialog box units to pixels.
MapDialogRect(hwndDlg, &rcTab);

// Calculate how large to make the tab control, so
// the display area can accommodate all the child dialog boxes.
TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab);
OffsetRect(&rcTab, cxMargin - rcTab.left, cyMargin - rcTab.top);

// Calculate the display rectangle.
CopyRect(&pHdr->rcDisplay, &rcTab);
TabCtrl_AdjustRect(pHdr->hwndTab, FALSE, &pHdr->rcDisplay);

// Set the size and position of the tab control, buttons,
// and dialog box.
SetWindowPos(pHdr->hwndTab, NULL, rcTab.left, rcTab.top,
rcTab.right - rcTab.left, rcTab.bottom - rcTab.top,
SWP_NOZORDER);

// Move the first button below the tab control.
hwndButton = GetDlgItem(hwndDlg, IDB_CLOSE);
SetWindowPos(hwndButton, NULL,
rcTab.left, rcTab.bottom + cyMargin, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);

// Determine the size of the button.
GetWindowRect(hwndButton, &rcButton);
rcButton.right -= rcButton.left;
rcButton.bottom -= rcButton.top;

// Move the second button to the right of the first.
hwndButton = GetDlgItem(hwndDlg, IDB_TEST);
SetWindowPos(hwndButton, NULL,
rcTab.left + rcButton.right + cxMargin,
rcTab.bottom + cyMargin, 0, 0,
SWP_NOSIZE | SWP_NOZORDER);

// Size the dialog box.
SetWindowPos(hwndDlg, NULL, 0, 0,
rcTab.right + cyMargin + (2 * GetSystemMetrics(SM_CXDLGFRAME)),
rcTab.bottom + rcButton.bottom + (2 * cyMargin)
+ (2 * GetSystemMetrics(SM_CYDLGFRAME))
+ GetSystemMetrics(SM_CYCAPTION),
SWP_NOMOVE | SWP_NOZORDER);

// Simulate selection of the first item.
OnSelChanged(hwndDlg);

return S_OK;
}
DLGTEMPLATEEX* DoLockDlgRes(LPCTSTR lpszResName)
{
HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG);

// Note that g_hInst is the global instance handle
HGLOBAL hglb = LoadResource(g_hInst, hrsrc);
return (DLGTEMPLATEEX *) LockResource(hglb);
}
VOID OnSelChanged(HWND hwndDlg)
{
// Get the dialog header data.
DLGHDR *pHdr = (DLGHDR *) GetWindowLong(
hwndDlg, GWL_USERDATA);

// Get the index of the selected tab.
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);

// Destroy the current child dialog box, if any.
if (pHdr->hwndDisplay != NULL)
DestroyWindow(pHdr->hwndDisplay);

// Create the new child dialog box. Note that g_hInst is the
// global instance handle.
pHdr->hwndDisplay = CreateDialogIndirect(g_hInst,
(DLGTEMPLATE *)pHdr->apRes[iSel], hwndDlg, ChildDialogProc);

return;
}
BOOL __stdcall ChildDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
{

}
break;

case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:

break;
case IDCANCEL:
::EndDialog (hDlg, IDCANCEL);
break;
}
break;
}
return 0;
}

备注:
编程环境VC6.0
第一个问题:,经过调试发现:
pHdr->apRes[0]->cx=68
pHdr->apRes[1]->cx=68
pHdr->apRes[2]->cx=68
pHdr->apRes[0]->cy=105
pHdr->apRes[1]->cy=105
pHdr->apRes[2]->cy=105
为什么,我的rc文件中的三个对话框的描述都不是这个宽度和高度????

第二个问题
// Map the rectangle from dialog box units to pixels.
MapDialogRect(hwndDlg, &rcTab);
这个函数到底是干嘛的?经过这个函数调用以后,68变成了136,105变成了210,都变成原先的二倍,不理解。
第三个问题
TabCtrl_AdjustRect(pHdr->hwndTab, TRUE, &rcTab);
这个函数到底是干嘛的?弄的头大。
...全文
300 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
ooolinux 2016-12-09
  • 打赏
  • 举报
回复
引用 8 楼 ZiSheng 的回复:
c+ +builder不也是调用windows–api吗?他怎么会简单!
它做了很多包装,代码量很少,而且界面可以用鼠标拖拉控件来设计,不写一行代码。
赵4老师 2016-12-09
  • 打赏
  • 举报
回复
Coordinate Space and Transformation Functions The following functions are used with coordinate spaces and transformations. ClientToScreen CombineTransform DPtoLP GetCurrentPositionEx GetGraphicsMode GetMapMode GetViewportExtEx GetViewportOrgEx GetWindowExtEx GetWindowOrgEx GetWorldTransform LPtoDP MapWindowPoints ModifyWorldTransform OffsetViewportOrgEx OffsetWindowOrgEx ScaleViewportExtEx ScaleWindowExtEx ScreenToClient SetGraphicsMode SetMapMode SetViewportExtEx SetViewportOrgEx SetWindowExtEx SetWindowOrgEx SetWorldTransform
ZiSheng 2016-12-09
  • 打赏
  • 举报
回复
c+ +builder不也是调用windows–api吗?他怎么会简单!
ZiSheng 2016-12-09
  • 打赏
  • 举报
回复
解释不对,我的三个对话框宽度和高度各不一样,请看rc文件,获取的结果却是一样的!!!
paschen 2016-12-08
  • 打赏
  • 举报
回复
1、用的单位是不同的,运行时获取的默认是像素 2、https://msdn.microsoft.com/en-us/library/ms645502(v=vs.85).aspx Converts the specified dialog box units to screen units (pixels). The function replaces the coordinates in the specified RECT structure with the converted coordinates, which allows the structure to be used to create a dialog box or position a control within a dialog box. 3、TabCtrl_AdjustRect是个宏,相当于发送TCM_ADJUSTRECT消息,调整控件大小 https://msdn.microsoft.com/zh-cn/library/bb760645
ooolinux 2016-12-08
  • 打赏
  • 举报
回复
SDK编程挺繁琐的,不知道楼主对C++ Builder有没有兴趣呢?可以了解一下。 图形用户界面学习C++ Builder,入门比较容易。 仅供参考: 初学者学习C++ Builder第一个程序(模拟聊天室),经典! http://blog.163.com/tab_98/blog/static/11924097201693033057497/ C++ Builder绘图示例(模拟时钟) http://blog.163.com/tab_98/blog/static/11924097201611324819376/ 从C语言的菜单界面管理系统到C++ Builder的图形用户界面,一个简单的电话簿Demo例子 http://blog.163.com/tab_98/blog/static/1192409720158673337998/ C++ Builder写的《ZEC 纸牌游戏21点》 http://blog.163.com/tab_98/blog/static/119240972016115113039304/ C++ Builder写的《ZEC 僵尸版打地鼠》 http://blog.163.com/tab_98/blog/static/11924097201601084117748/ 书籍推荐: 《C++Builder 6程序设计教程(第二版)》 (陆卫忠,刘文亮 等编著 /2011-04-01 /科学出版社) 《C++Builder6编程实例精解》(赵明现),PDF,是数字版的,非扫描版的,里面还有一个俄罗斯方块游戏的完整实现。 《精彩C++Builder 6程序设计》(台湾 吴逸贤),里面有10几个简单小游戏的实现,可以自己看懂以后再重写,才是自己掌握的。 《C++ Builder 5高级编程实例精解》(刘滨 编著)都是较大的实用的程序。
ZiSheng 2016-12-08
  • 打赏
  • 举报
回复
赵老师,第二个问题和第三个问题似乎明白了,第一个问题呢?怎么解释呢
ZiSheng 2016-12-08
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
MapDialogRect The MapDialogRect function converts (maps) the specified dialog box units to screen units (pixels). The function replaces the coordinates in the specifiedRECT structure with the converted coordinates, which allows the structure to be used to create a dialog box or position a control within a dialog box. BOOL MapDialogRect( HWND hDlg, // handle of dialog box LPRECT lpRect // address of structure with rectangle ); Parameters hDlg Identifies a dialog box. This function accepts only handles for dialog boxes created by one of the dialog box creation functions; handles for other windows are not valid. lpRect Pointer to a RECT structure that contains the dialog box coordinates to be converted. Return Values If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, callGetLastError. Remarks The MapDialogRect function assumes that the initial coordinates in theRECT structure represent dialog box units. To convert these coordinates from dialog box units to pixels, the function retrieves the current horizontal and vertical base units for the dialog box, then applies the following formulas: left = (left * baseunitX) / 4 right = (right * baseunitX) / 4 top = (top * baseunitY) / 8 bottom = (bottom * baseunitY) / 8 In most cases, the base units for the dialog box are the same as those retrieved by using the GetDialogBaseUnits function. If the dialog box template has the DS_SETFONT style, however, the base units are the average width and height, in pixels, of the characters in the font given by the template. QuickInfo Windows NT: Requires version 3.1 or later. Windows: Requires Windows 95 or later. Windows CE: Requires version 1.0 or later. Header: Declared in winuser.h. Import Library: Use user32.lib. See Also Dialog Boxes Overview, Dialog Box Functions, CreateDialog, CreateDialogIndirect, CreateDialogIndirectParam, CreateDialogParam, DialogBox, DialogBoxIndirect, DialogBoxIndirectParam, DialogBoxParam, GetDialogBaseUnits,RECT TabCtrl_AdjustRect VOID TabCtrl_AdjustRect( HWND hwnd, BOOL fLarger, RECT FAR *prc ); Calculates a tab control's display area given a window rectangle, or calculates the window rectangle that would correspond to a specified display area. You can use this macro or send the TCM_ADJUSTRECT message explicitly. No return value. hwnd Handle to the tab control. fLarger Operation to perform. If this parameter is TRUE, prc specifies a display rectangle and receives the corresponding window rectangle. If this parameter is FALSE, prc specifies a window rectangle and receives the corresponding display area. prc Address of aRECT structure that specifies the given rectangle and receives the calculated rectangle. -------------------------------------------------------------------------------- Top of Page © 1997 Microsoft Corporation. All rights reserved. Terms of Use.
赵老师,第二个问题和第三个问题似乎明白了,第一个问题呢?怎么解释呢?
赵4老师 2016-12-08
  • 打赏
  • 举报
回复
MapDialogRect The MapDialogRect function converts (maps) the specified dialog box units to screen units (pixels). The function replaces the coordinates in the specifiedRECT structure with the converted coordinates, which allows the structure to be used to create a dialog box or position a control within a dialog box. BOOL MapDialogRect( HWND hDlg, // handle of dialog box LPRECT lpRect // address of structure with rectangle ); Parameters hDlg Identifies a dialog box. This function accepts only handles for dialog boxes created by one of the dialog box creation functions; handles for other windows are not valid. lpRect Pointer to a RECT structure that contains the dialog box coordinates to be converted. Return Values If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, callGetLastError. Remarks The MapDialogRect function assumes that the initial coordinates in theRECT structure represent dialog box units. To convert these coordinates from dialog box units to pixels, the function retrieves the current horizontal and vertical base units for the dialog box, then applies the following formulas: left = (left * baseunitX) / 4 right = (right * baseunitX) / 4 top = (top * baseunitY) / 8 bottom = (bottom * baseunitY) / 8 In most cases, the base units for the dialog box are the same as those retrieved by using the GetDialogBaseUnits function. If the dialog box template has the DS_SETFONT style, however, the base units are the average width and height, in pixels, of the characters in the font given by the template. QuickInfo Windows NT: Requires version 3.1 or later. Windows: Requires Windows 95 or later. Windows CE: Requires version 1.0 or later. Header: Declared in winuser.h. Import Library: Use user32.lib. See Also Dialog Boxes Overview, Dialog Box Functions, CreateDialog, CreateDialogIndirect, CreateDialogIndirectParam, CreateDialogParam, DialogBox, DialogBoxIndirect, DialogBoxIndirectParam, DialogBoxParam, GetDialogBaseUnits,RECT TabCtrl_AdjustRect VOID TabCtrl_AdjustRect( HWND hwnd, BOOL fLarger, RECT FAR *prc ); Calculates a tab control's display area given a window rectangle, or calculates the window rectangle that would correspond to a specified display area. You can use this macro or send the TCM_ADJUSTRECT message explicitly. No return value. hwnd Handle to the tab control. fLarger Operation to perform. If this parameter is TRUE, prc specifies a display rectangle and receives the corresponding window rectangle. If this parameter is FALSE, prc specifies a window rectangle and receives the corresponding display area. prc Address of aRECT structure that specifies the given rectangle and receives the calculated rectangle. -------------------------------------------------------------------------------- Top of Page © 1997 Microsoft Corporation. All rights reserved. Terms of Use.
ZiSheng 2016-12-08
  • 打赏
  • 举报
回复
rc资源文件如下:

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Chinese (P.R.C.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_MAIN DIALOG DISCARDABLE  0, 0, 288, 96
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
    DEFPUSHBUTTON   "OK",IDB_CLOSE,33,49,65,14
    PUSHBUTTON      "Cancel",IDB_TEST,108,46,50,14
END

IDD_FIRSTDLG DIALOG DISCARDABLE  0, 0, 367, 154
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,310,7,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,310,24,50,14
END

IDD_SECONDDLG DIALOG DISCARDABLE  0, 0, 187, 96
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,130,7,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,130,24,50,14
END

IDD_THIRDDLG DIALOG DISCARDABLE  0, 0, 187, 216
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 10, "System"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,130,7,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,130,24,50,14
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE 
BEGIN
    IDD_MAIN, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 281
        TOPMARGIN, 7
        BOTTOMMARGIN, 89
    END

    IDD_FIRSTDLG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 360
        TOPMARGIN, 7
        BOTTOMMARGIN, 147
    END

    IDD_SECONDDLG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 180
        TOPMARGIN, 7
        BOTTOMMARGIN, 89
    END

    IDD_THIRDDLG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 180
        TOPMARGIN, 7
        BOTTOMMARGIN, 209
    END
END
#endif    // APSTUDIO_INVOKED


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

#endif    // Chinese (P.R.C.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED


[/code]

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧