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

「已注销」 「已注销」 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
曾经发过一篇帖子《关于扩展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;
}
...全文
评论 9
收藏 已收藏
分享
返回顶部
「已注销」
界面 15,976 成员 115,866 内容