分享WTL布局类,感谢各位的援手!

老邓 2011-04-15 12:22:53
曾经发过一篇帖子《关于扩展WTL,请帮我提供下灵感?》,得到了众多高手的指点。
奈何自己一直未曾实践,惭愧!!

这几天重新学习WTL,顺便改写了一个布局类,由于改写自atlframe.h中附带的CDialogResize,所以并没有技术含量。
我所做的:
1. 数据保存的不再是ID,而是HWND,性能上略有提升:不必再反复调用GetDlgItem了。
2. 由于数据保存的是HWND,这给无ID动态创建的控件提供了方便:
// Can be called after initialization
void AddResizableItem(HWND hWnd, DWORD dwFlag)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
ATLASSERT(::IsWindow(hWnd));
RECT rectCtl = { 0 };
::GetWindowRect(hWnd, &rectCtl);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
_AtlResizeData data = { hWnd, dwFlag, rectCtl };
m_arrData.Add(data);
}

大家可以看到,可以在初始化布局器后,动态添加控件到布局器了。
用法:
BOOL CMainDialog::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/)
{
。。。
InitResizable();
AddResizableItem(m_edtTest, R_SIZE_X | R_SIZE_Y);
。。。
return TRUE;
}

3. 窗口大小调节句柄默认太宽了,我给修正了一下:右边不会感觉太空了。
4. 代码风格修改:不喜欢带下划线的函数。
5. 类名修改成:CResizable,适用于一切有子窗口的类继承它,包括框架窗口。

完整事例来自一个不依赖资源动态创建的对话框,大家看看效果如何。
头文件:
#pragma once

#include "atlresize.h"

class CMainDialog : public CIndirectDialogImpl<CMainDialog>, public CResizable<CMainDialog>
{
public:
enum
{
ID_BTN1 = 2000,
ID_BTN2,
};

BEGIN_MSG_MAP(CMainDialog)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_CLOSE(OnClose)
COMMAND_ID_HANDLER_EX(ID_BTN1, OnButton1Click)
COMMAND_ID_HANDLER_EX(ID_BTN2, OnButton2Click)
CHAIN_MSG_MAP(CResizable<CMainDialog>)
END_MSG_MAP()

BEGIN_RESIZE_MAP(CMainDialog)
RESIZE_CONTROL(ID_BTN1, R_MOVE_X | R_MOVE_Y)
RESIZE_CONTROL(ID_BTN2, R_MOVE_X | R_MOVE_Y)
END_RESIZE_MAP()

void DoInitTemplate();
void DoInitControls();

BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
void OnClose();
void OnButton1Click(UINT uNotifyCode, int nID, CWindow wndCtl);
void OnButton2Click(UINT uNotifyCode, int nID, CWindow wndCtl);

protected:
CButton m_btnTest[2];
CEdit m_edtTest;
};

源文件:
#include "StdAfx.h"
#include "MainDialog.h"

void CMainDialog::DoInitTemplate()
{
m_Template.Create(true,
_T("Indirect Dialog"),
CRect(0, 0, 300, 200),
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0,
_T("Ms Shell Dlg"),
8
);
}

void CMainDialog::DoInitControls()
{
}

BOOL CMainDialog::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/)
{
MoveWindow(CRect(0, 0, 228, 163), FALSE);

m_edtTest.Create(m_hWnd, (LPRECT)CRect(10, 10, 200, 80), _T("文本"), WS_CHILD | WS_VISIBLE);
m_edtTest.SetFont(GetFont());

m_btnTest[0].Create(m_hWnd, (LPRECT)CRect(10, 90, 90, 118), _T("按钮一"),
WS_CHILD | WS_VISIBLE, 0, ID_BTN1);
m_btnTest[0].SetFont(GetFont());
m_btnTest[1].Create(m_hWnd, (LPRECT)CRect(100, 90, 190, 118), _T("按钮二"),
WS_CHILD | WS_VISIBLE, 0, ID_BTN2);
m_btnTest[1].SetFont(GetFont());

InitResizable();
AddResizableItem(m_edtTest, R_SIZE_X | R_SIZE_Y);

CenterWindow();
SetMsgHandled(FALSE);
return TRUE;
}

void CMainDialog::OnClose()
{
EndDialog(IDOK);
SetMsgHandled(FALSE);
}

void CMainDialog::OnButton1Click(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wndCtl*/)
{
MessageBox(_T("OnButton1Click"));
}

void CMainDialog::OnButton2Click(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wndCtl*/)
{
MessageBox(_T("OnButton2Click"));
}


将下面内容保存为atlresize.h,可以作为WTL的扩展在工程中使用。
欢迎大家继续改良及批评指正!!

#ifndef __ATLRESIZE_H__
#define __ATLRESIZE_H__

#pragma once

#ifndef __ATLBASE_H__
#error atlresize.h requires atlbase.h to be included first
#endif

#ifndef __ATLWIN_H__
#error atlresize.h requires atlwin.h to be included first
#endif

///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
// CResizable

namespace WTL
{

///////////////////////////////////////////////////////////////////////////////
// CResizable - provides support for resizing dialog controls
// (works for any window that has child controls)

// Put CResizable in the list of base classes for a dialog (or even plain window),
// then implement RESIZE map by specifying controls and groups of control
// and using R_* values to specify how are they supposed to be resized.
//
// Notes:
// - Resizeable border (WS_THICKFRAME style) should be set in the dialog template
// for top level dialogs (popup or overlapped), so that users can resize the dialog.
// - Some flags cannot be combined; for instance R_CENTER_X overrides R_SIZE_X,
// R_SIZE_X overrides R_MOVE_X. X and Y flags can be combined.
// - Order of controls is important - group controls are resized and moved based
// on the position of the previous control in a group.

// dialog resize map macros
#define BEGIN_RESIZE_MAP(thisClass) \
static const _AtlResizeMap* GetResizeMap() \
{ \
static const _AtlResizeMap theMap[] = \
{

#define END_RESIZE_MAP() \
{ -1, 0 }, \
}; \
return theMap; \
}

#define RESIZE_CONTROL(id, flags) \
{ id, flags },

#define BEGIN_RESIZE_GROUP() \
{ -1, _R_BEGIN_GROUP },

#define END_RESIZE_GROUP() \
{ -1, _R_END_GROUP },


template <typename T>
class CResizable
{
public:
// Data declarations and members
enum
{
R_SIZE_X = 0x00000001,
R_SIZE_Y = 0x00000002,
R_MOVE_X = 0x00000004,
R_MOVE_Y = 0x00000008,
R_REPAINT = 0x00000010,
R_CENTER_X = 0x00000020,
R_CENTER_Y = 0x00000040,
// internal use only
_R_BEGIN_GROUP = 0x00001000,
_R_END_GROUP = 0x00002000,
_R_GRIPPER = 0x00004000
};

struct _AtlResizeMap
{
int m_nCtlID;
DWORD m_dwResizeFlags;
};

struct _AtlResizeData
{
HWND m_hWnd;
DWORD m_dwResizeFlags;
RECT m_rect;

int GetGroupCount() const
{
return (int)LOBYTE(HIWORD(m_dwResizeFlags));
}

void SetGroupCount(int nCount)
{
ATLASSERT(nCount > 0 && nCount < UCHAR_MAX);
DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0));
m_dwResizeFlags &= 0xFF00FFFF;
m_dwResizeFlags |= dwCount;
}

bool operator ==(const _AtlResizeData& r) const
{
return (m_hWnd == r.m_hWnd && m_dwResizeFlags == r.m_dwResizeFlags);
}
};

CResizable() :
m_bGripper(false)
{
m_sizeParent.cx = 0;
m_sizeParent.cy = 0;
m_ptMinTrackSize.x = -1;
m_ptMinTrackSize.y = -1;
}
...全文
362 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
老邓 2011-04-16
  • 打赏
  • 举报
回复
基本上看明白了。
这个WTL内置的布局功能还是很有限的。
老邓 2011-04-15
  • 打赏
  • 举报
回复
疑问:
请介绍一下:
#define BEGIN_DLGRESIZE_GROUP() \
{ -1, _DLSZ_BEGIN_GROUP },

#define END_DLGRESIZE_GROUP() \
{ -1, _DLSZ_END_GROUP },

的用法,谢谢!!
我对这两个宏的用法一直不理解。
老邓 2011-04-15
  • 打赏
  • 举报
回复

BEGIN_MSG_MAP(CResizable)
MESSAGE_HANDLER(WM_SIZE, OnSize)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
#endif // _WIN32_WCE
END_MSG_MAP()

LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
#ifndef _WIN32_WCE
if(m_bGripper)
{
ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
if(wParam == SIZE_MAXIMIZED)
wndGripper.ShowWindow(SW_HIDE);
else if(wParam == SIZE_RESTORED)
wndGripper.ShowWindow(SW_SHOW);
}
#endif // _WIN32_WCE
if(wParam != SIZE_MINIMIZED)
{
ATLASSERT(::IsWindow(pT->m_hWnd));
pT->UpdateResizable(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
return 0;
}

#ifndef _WIN32_WCE
LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
if (m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
{
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
lpMMI->ptMinTrackSize = m_ptMinTrackSize;
}
return 0;
}
#endif // _WIN32_WCE

bool PositionControlResizable(int cxWidth, int cyHeight, RECT& rectGroup, _AtlResizeData& data,
bool bGroup, _AtlResizeData* pDataPrev = NULL)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
RECT rectCtl = { 0 };

ATL::CWindow ctl(data.m_hWnd);
if (!ctl.GetWindowRect(&rectCtl))
return false;
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);

if (bGroup)
{
if ((data.m_dwResizeFlags & R_CENTER_X) != 0)
{
int cxRight = rectGroup.right + cxWidth - m_sizeParent.cx;
int cxCtl = data.m_rect.right - data.m_rect.left;
rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2;
rectCtl.right = rectCtl.left + cxCtl;
}
else if ((data.m_dwResizeFlags & (R_SIZE_X | R_MOVE_X)) != 0)
{
rectCtl.left = rectGroup.left
+ ::MulDiv(data.m_rect.left - rectGroup.left,
rectGroup.right - rectGroup.left + (cxWidth - m_sizeParent.cx),
rectGroup.right - rectGroup.left);

if ((data.m_dwResizeFlags & R_SIZE_X) != 0)
{
rectCtl.right = rectGroup.left
+ ::MulDiv(data.m_rect.right - rectGroup.left,
rectGroup.right - rectGroup.left + (cxWidth - m_sizeParent.cx),
rectGroup.right - rectGroup.left);

if (pDataPrev != NULL)
{
ATL::CWindow ctlPrev(pDataPrev->m_hWnd);
RECT rcPrev = { 0 };
ctlPrev.GetWindowRect(&rcPrev);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
int dxAdjust = (rectCtl.left - rcPrev.right)
- (data.m_rect.left - pDataPrev->m_rect.right);
rcPrev.right += dxAdjust;
ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
}
}
else
{
rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left);
}
}

if ((data.m_dwResizeFlags & R_CENTER_Y) != 0)
{
int cyBottom = rectGroup.bottom + cyHeight - m_sizeParent.cy;
int cyCtl = data.m_rect.bottom - data.m_rect.top;
rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2;
rectCtl.bottom = rectCtl.top + cyCtl;
}
else if ((data.m_dwResizeFlags & (R_SIZE_Y | R_MOVE_Y)) != 0)
{
rectCtl.top = rectGroup.top
+ ::MulDiv(data.m_rect.top - rectGroup.top,
rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeParent.cy),
rectGroup.bottom - rectGroup.top);

if ((data.m_dwResizeFlags & R_SIZE_Y) != 0)
{
rectCtl.bottom = rectGroup.top
+ ::MulDiv(data.m_rect.bottom - rectGroup.top,
rectGroup.bottom - rectGroup.top
+ (cyHeight - m_sizeParent.cy),
rectGroup.bottom - rectGroup.top);

if (pDataPrev != NULL)
{
ATL::CWindow ctlPrev(pDataPrev->m_hWnd);
RECT rcPrev = { 0 };
ctlPrev.GetWindowRect(&rcPrev);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
int dxAdjust = (rectCtl.top - rcPrev.bottom)
- (data.m_rect.top - pDataPrev->m_rect.bottom);
rcPrev.bottom += dxAdjust;
ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
}
}
else
{
rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top);
}
}
}
else // no group
{
if ((data.m_dwResizeFlags & R_CENTER_X) != 0)
{
int cxCtl = data.m_rect.right - data.m_rect.left;
rectCtl.left = (cxWidth - cxCtl) / 2;
rectCtl.right = rectCtl.left + cxCtl;
}
else if ((data.m_dwResizeFlags & (R_SIZE_X | R_MOVE_X)) != 0)
{
rectCtl.right = data.m_rect.right + (cxWidth - m_sizeParent.cx);

if ((data.m_dwResizeFlags & R_MOVE_X) != 0)
rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left);
}

if ((data.m_dwResizeFlags & R_CENTER_Y) != 0)
{
int cyCtl = data.m_rect.bottom - data.m_rect.top;
rectCtl.top = (cyHeight - cyCtl) / 2;
rectCtl.bottom = rectCtl.top + cyCtl;
}
else if ((data.m_dwResizeFlags & (R_SIZE_Y | R_MOVE_Y)) != 0)
{
rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeParent.cy);

if ((data.m_dwResizeFlags & R_MOVE_Y) != 0)
rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top);
}
}

if ((data.m_dwResizeFlags & R_REPAINT) != 0)
ctl.Invalidate();

if ((data.m_dwResizeFlags
& (R_SIZE_X | R_SIZE_Y | R_MOVE_X | R_MOVE_Y | R_REPAINT | R_CENTER_X | R_CENTER_Y))
!= 0)
{
ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE);
}

return true;
}

protected:
ATL::CSimpleArray<_AtlResizeData> m_arrData;
SIZE m_sizeParent;
POINT m_ptMinTrackSize;
bool m_bGripper;
};


} // namespace WTL

#endif // __ATLRESIZE_H__
老邓 2011-04-15
  • 打赏
  • 举报
回复

void InitResizable(bool bAddGripper = true, bool bUseMinTrackSize = true,
DWORD dwForceStyle = WS_CLIPCHILDREN)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));

DWORD dwStyle = pT->GetStyle();

// Force specified styles (default WS_CLIPCHILDREN reduces flicker)
if ((dwStyle & dwForceStyle) != dwForceStyle)
pT->ModifyStyle(0, dwForceStyle);

// Adding this style removes an empty icon that dialogs with WS_THICKFRAME have.
// Setting icon to NULL is required when XP themes are active.
// Note: This will not prevent adding an icon for the dialog using SetIcon()
if ((dwStyle & WS_CHILD) == 0)
{
pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME);
if (pT->GetIcon(FALSE) == NULL)
pT->SetIcon(NULL, FALSE);
}

// Cleanup in case of multiple initialization
// block: first check for the gripper control, destroy it if needed
{
ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
if (wndGripper.IsWindow() && m_arrData.GetSize() > 0
&& (m_arrData[0].m_dwResizeFlags & _R_GRIPPER) != 0)
wndGripper.DestroyWindow();
}

// clear out everything else
m_arrData.RemoveAll();
m_sizeParent.cx = 0;
m_sizeParent.cy = 0;
m_ptMinTrackSize.x = -1;
m_ptMinTrackSize.y = -1;

// Get initial parent client size
RECT rectParent = { 0 };
pT->GetClientRect(&rectParent);
rectParent.right -= 9; // hack for best show
m_sizeParent.cx = rectParent.right;
m_sizeParent.cy = rectParent.bottom;

#ifndef _WIN32_WCE
// Create gripper if requested
if (bAddGripper)
{
// shouldn't exist already
ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)));
if (!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)))
{
ATL::CWindow wndGripper;
wndGripper.Create(_T("SCROLLBAR"),
pT->m_hWnd,
rectParent,
NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGRIP
| SBS_SIZEBOXBOTTOMRIGHTALIGN,
0,
ATL_IDW_STATUS_BAR);
ATLASSERT(wndGripper.IsWindow());
if (wndGripper.IsWindow())
{
m_bGripper = true;
RECT rectCtl = { 0 };
wndGripper.GetWindowRect(&rectCtl);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
_AtlResizeData data =
{ wndGripper, R_MOVE_X | R_MOVE_Y | R_REPAINT | _R_GRIPPER, rectCtl };
m_arrData.Add(data);
}
}
}
#else // CE specific
bAddGripper; // avoid level 4 warning
#endif // _WIN32_WCE
// Get min track position if requested
if (bUseMinTrackSize)
{
if ((dwStyle & WS_CHILD) != 0)
{
RECT rect = { 0 };
pT->GetClientRect(&rect);
m_ptMinTrackSize.x = rect.right - rect.left;
m_ptMinTrackSize.y = rect.bottom - rect.top;
}
else
{
RECT rect = { 0 };
pT->GetWindowRect(&rect);
m_ptMinTrackSize.x = rect.right - rect.left;
m_ptMinTrackSize.y = rect.bottom - rect.top;
}
}

// Walk the map and initialize data
const _AtlResizeMap* pMap = pT->GetResizeMap();
ATLASSERT(pMap != NULL);
int nGroupStart = -1;
for (int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++)
{
if (pMap->m_nCtlID == -1)
{
switch (pMap->m_dwResizeFlags)
{
case _R_BEGIN_GROUP:
ATLASSERT(nGroupStart == -1);
nGroupStart = m_arrData.GetSize();
break;
case _R_END_GROUP:
{
ATLASSERT(nGroupStart != -1);
int nGroupCount = m_arrData.GetSize() - nGroupStart;
m_arrData[nGroupStart].SetGroupCount(nGroupCount);
nGroupStart = -1;
break;
}
default:
ATLASSERT(FALSE && _T("Invalid RESIZE Map Entry"));
break;
}
}
else
{
// this ID conflicts with the default gripper one
ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE);

ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID);
ATLASSERT(ctl.IsWindow());
RECT rectCtl = { 0 };
ctl.GetWindowRect(&rectCtl);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);

DWORD dwGroupFlag =
(nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _R_BEGIN_GROUP : 0;
_AtlResizeData data = { ctl, pMap->m_dwResizeFlags | dwGroupFlag, rectCtl };
m_arrData.Add(data);
}
}
ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the RESIZE Map"));
}

// Can be called after initialization
void AddResizableItem(HWND hWnd, DWORD dwFlag)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
ATLASSERT(::IsWindow(hWnd));
RECT rectCtl = { 0 };
::GetWindowRect(hWnd, &rectCtl);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
_AtlResizeData data = { hWnd, dwFlag, rectCtl };
m_arrData.Add(data);
}

void UpdateResizable(int cxWidth, int cyHeight)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));

// Restrict minimum size if requested
if (((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
{
if (cxWidth < m_ptMinTrackSize.x)
cxWidth = m_ptMinTrackSize.x;
if (cyHeight < m_ptMinTrackSize.y)
cyHeight = m_ptMinTrackSize.y;
}

BOOL bVisible = pT->IsWindowVisible();
if (bVisible)
pT->SetRedraw(FALSE);

for (int i = 0; i < m_arrData.GetSize(); i++)
{
if ((m_arrData[i].m_dwResizeFlags & _R_BEGIN_GROUP) != 0) // start of a group
{
int nGroupCount = m_arrData[i].GetGroupCount();
ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize());
RECT rectGroup = m_arrData[i].m_rect;

int j = 1;
for (j = 1; j < nGroupCount; j++)
{
rectGroup.left = min(rectGroup.left, m_arrData[i + j].m_rect.left);
rectGroup.top = min(rectGroup.top, m_arrData[i + j].m_rect.top);
rectGroup.right = max(rectGroup.right, m_arrData[i + j].m_rect.right);
rectGroup.bottom = max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom);
}

for (j = 0; j < nGroupCount; j++)
{
_AtlResizeData* pDataPrev = NULL;
if (j > 0)
pDataPrev = &(m_arrData[i + j - 1]);
pT->PositionControlResizable(cxWidth,
cyHeight,
rectGroup,
m_arrData[i + j],
true,
pDataPrev);
}

i += nGroupCount - 1; // increment to skip all group controls
}
else // one control entry
{
RECT rectGroup = { 0, 0, 0, 0 };
pT->PositionControlResizable(cxWidth, cyHeight, rectGroup, m_arrData[i], false);
}
}

if (bVisible)
pT->SetRedraw(TRUE);

pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
}
老邓 2011-04-15
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 xianglitian 的回复:]

老邓大驾光临过来捧个场
有时间再仔细看看
[/Quote]
岂敢!正在看源码,还没看明白GROUP的原理。
还请多多指教!!
QQ282881515 2011-04-15
  • 打赏
  • 举报
回复
最近也在学习WTL,学习了
向立天 2011-04-15
  • 打赏
  • 举报
回复
老邓大驾光临过来捧个场
有时间再仔细看看
无水先生 2011-04-15
  • 打赏
  • 举报
回复
请教这句何意?
T* pT = static_cast<T*>(this);

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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