vc自绘控件总结

想必很多使用MFC编程的朋友都想去用微软的控件,但是很多时候我们发现控件的功能并没有想象中的那么强大,而且很多功能我们根本都用不到,我们想去自绘控件,但是又不知道如何着手。本文介绍MFC控件设计的大致步骤。

Window窗口中的控件都是有一系列的窗口组成。其实按钮就是一个窗口,至于它是如何能嵌入到其他的窗口中呢,这就关系到一个父窗口的问题了,即按钮必须是父窗口的子窗口,并且父窗口移动及时通知子窗口移动。

了解了以上,我们就来看一下自绘控件的大致步骤吧
①重载窗口类CShowDlg,在这里我们重载的基类为CDialog 对话框类

②插入对话框资源 IDD_DIALOG1,并绑定刚刚重载的窗口类CShowDlg

③定义重载的窗口类变量m_MyControl,并为定义的变量设计窗口风格,由于控件是一定要贴入到窗口中的,而不是弹出来,所以对话框设计风格一定要有WS_CHILD类型

④子窗口随父窗口一起移动,父窗口为对话框类,为此我们可以在父窗口上添加消息映射 ON_WM_MOVE()ON_WM_SIZE()及时获取父窗口的移动以及大小变化,并且使父窗口能够及时通知子窗口移动窗口以及改变窗口大小等命令。

⑤控件是禁止被鼠标拖动的,所以必须去掉标题栏属性,这样控件就不会移动了。

知道了MFC的基本原理,设计自己需要的控件不再那么难。

void CShowDlg::OnMove(int x, int y) 
{
    CDialog::OnMove(x, y);

    // TODO: Add your message handler code here
    //在移动窗口之前一定要确保m_MyControl已经创建
    if (::IsWindow(m_MyControl.GetSafeHwnd()))
    {
        //x,y为父窗口左上角的坐标,子窗口CRect区域为[10,20,300,400]
        m_MyControl.MoveWindow(x+10,y+20,300,400);
        // m_MyControl.SetWindowPos(NULL,x+10,y+20,300,400,SWP_NOSIZE);
    }
}

窗口设计风格如下所示。

ModifyStyle(0, WS_CLIPCHILDREN);//
BOOL ModifyStyle
(
    DWORD dwRemove,// 指定修改时要删除的窗风格
    DWORD dwAdd,//指定修改时将要增加的窗口风格
    UINT nFlags=0//该参数将被传给SetWindowPos,否则为0,如果SetWindowPos不被调用的话,一般该参数默认值
);//如果该函数成功调用返回一个非0值,否则返回0;

/*
    如果nFlags不为0, ModifyStyle将调用Windows API 函数SetWindowPos并且结合nFlags和以下四个预先布置好的标志重画该窗口。
    SWP_NOSIZE 保持当前大小。
    SWP_NOMOVE 保持当前位置.。
    SWP_NOZORDER 保持当前的Z次序。
    SWP_NOACTIVATE 不激活该窗口。
*/

//WinUser.h中的窗口风格如下所示。
/*
 * Window Styles
 */
#define WS_OVERLAPPED       0x00000000L
#define WS_POPUP            0x80000000L
#define WS_CHILD            0x40000000L
#define WS_MINIMIZE         0x20000000L
#define WS_VISIBLE          0x10000000L
#define WS_DISABLED         0x08000000L
#define WS_CLIPSIBLINGS     0x04000000L
#define WS_CLIPCHILDREN     0x02000000L
#define WS_MAXIMIZE         0x01000000L
#define WS_CAPTION          0x00C00000L     /* WS_BORDER | WS_DLGFRAME  */
#define WS_BORDER           0x00800000L
#define WS_DLGFRAME         0x00400000L
#define WS_VSCROLL          0x00200000L
#define WS_HSCROLL          0x00100000L
#define WS_SYSMENU          0x00080000L
#define WS_THICKFRAME       0x00040000L
#define WS_GROUP            0x00020000L
#define WS_TABSTOP          0x00010000L

#define WS_MINIMIZEBOX      0x00020000L
#define WS_MAXIMIZEBOX      0x00010000L


#define WS_TILED            WS_OVERLAPPED
#define WS_ICONIC           WS_MINIMIZE
#define WS_SIZEBOX          WS_THICKFRAME
#define WS_TILEDWINDOW      WS_OVERLAPPEDWINDOW

/*
 * Common Window Styles
 */
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)

#define WS_POPUPWINDOW      (WS_POPUP          | \
                             WS_BORDER         | \
                             WS_SYSMENU)

#define WS_CHILDWINDOW      (WS_CHILD)

其他需要了解的内容
获取屏幕大小
int nFullWidth = GetSystemMetris(SM_CXSCREEN);
int nFullHeight = GetSystemMetris(SM_CYSCREEN);

在窗口的大小更改后,框架调用该成员函数。

afx_msg void OnSize(
                       UINT nType,
                       int cx,
                       int cy 
                    );

参数 nType
指定请求的调整大小的类型。 此参数可以是下列值之一:
SIZE_MAXIMIZED 窗口最大化。
SIZE_MINIMIZED 窗口最小化。
SIZE_RESTORED 窗口已调整大小,但是,SIZE_MINIMIZED 和 SIZE_MAXIMIZED 不适用。
在某些其他窗口最大化时,SIZE_MAXHIDE 发送到所有弹出窗口。
在某些其他窗口将还原为其以前的大小时,SIZE_MAXSHOW 发送到所有弹出窗口。
cx 指定工作区的新的宽度。
cy 指定工作区的新的高度。

鼠标操作

afx_msg void OnLButtonDown( 
   UINT nFlags, //控制键信息
   CPoint point  //当前鼠标位置
);
Parameters
nFlags
Indicates whether various virtual keys are down. This parameter can be any combination of the following values:

MK_CONTROL   Set if the CTRL key is down.

MK_LBUTTON   Set if the left mouse button is down.

MK_MBUTTON   Set if the middle mouse button is down.

MK_RBUTTON   Set if the right mouse button is down.

MK_SHIFT   Set if the SHIFT key is down.

point
Specifies the x- and y-coordinate of the cursor. These coordinates are always relative to the upper-left corner of the window.
void CShowDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default

    CDialog::OnLButtonDown(nFlags, point);
}