1 注册窗口
2 创建窗口
3 窗口过程函数得到窗口类指针,调用类中的函数 OnPaint,OnSize,OnLButtonDown,OnLButtonUp,OnMouseMove,OnNCHitTest
4 定义区域
5 绘制区域
…
窗口过程函数代码如下:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
__asm nop;
CenterWindow(hWnd);
OnCreate(hWnd);
break;
case WM_SIZE:
OnSize(hWnd,wParam,lParam);
break;
case WM_MOUSELEAVE:
OnMouseLeave(hWnd,wParam,lParam);
break;
case WM_MOUSEMOVE:
OnMouseMove(hWnd,wParam,lParam);
break;
case WM_NCLBUTTONDBLCLK:
g_sys_frame.OnNcLButtionDbClk(hWnd,wParam,lParam);
break;
case WM_LBUTTONUP:
OnLButtonUp(hWnd,wParam,lParam);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hWnd,wParam,lParam);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS * p = (WINDOWPOS*)lParam;
int nMinWidth = 500;
if(p->cxcy,SWP_NOMOVE);
}
break;
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
OnPaint(hWnd,hdc);
EndPaint(hWnd, &ps);
break;
case WM_NCHITTEST:
return g_sys_frame.OnNcHitTest(hWnd,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
封装了一些On函数,这些函数在再调用类实现
void OnPaint(HWND hWnd,HDC hdc)
{
g_sys_frame.OnPaint(hWnd,hdc);
}
void OnCreate(HWND wnd)
{
g_sys_frame.Create(wnd);
}
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_sys_frame.OnLButtonDown(hWnd,wParam,lParam);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_sys_frame.OnLButtonUp(hWnd,wParam,lParam);
}
void OnMouseLeave(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_sys_frame.OnMouseLeave(hWnd);
}
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_sys_frame.OnMouseMove(hWnd,wParam,lParam);
}
void OnSize(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
RECT rcWin;
GetClientRect(hWnd,&rcWin);
g_sys_frame.OnSize(hWnd,wParam,lParam);
InvalidateRect(hWnd,&rcWin,FALSE);
}
g_sys_frame 是一个窗口的实现类
#ifndef system_frame_h
#define system_frame_h
#include "MyCloseBtn.h"
#include "MyMinBtn.h"
#include "MyMaxBtn.h"
#include "MyIcon.h"
//窗口的系统组件
//1 如何处理拉伸
//2 系统的按钮,最大,最小,关闭,icon,标题
//拉伸的矩形
struct ResizeRect
{
//拉伸的标志,HTLEFT ...
LRESULT resize_flag;
//拉伸的矩形
RECT resize_rect;
ResizeRect(){}
ResizeRect(RECT &rc,LRESULT flag)
{
resize_rect = rc;
resize_flag = flag;
}
void SetResizeRect(RECT &rc,LRESULT flag)
{
resize_rect = rc;
resize_flag = flag;
}
};
RECT MoveRectEx(RECT &rc,int dx,int dy)
{
RECT rcTmp=rc;
OffsetRect(&rcTmp,dx,dy);
return rcTmp;
}
inline RECT GenRect(int x,int y,int width,int height)
{
RECT rc={x,y,x+width,y+height};
return rc;
}
inline void GenResizeRect(RECT &rcWin,vector & ret_vec)
{
const int border_width = sys_frame_settings::get().border_width*4;
const int x_off = RECT_WIDTH(rcWin)-border_width*2;
const int y_off = RECT_HEIGHT(rcWin)-border_width*2;
//左上
RECT rc={0,0,border_width,border_width};
ret_vec.push_back(ResizeRect(rc,HTTOPLEFT));
ret_vec.push_back(ResizeRect(MoveRectEx(rc,x_off,0),HTTOPRIGHT));
ret_vec.push_back(ResizeRect(MoveRectEx(rc,0,y_off),HTBOTTOMLEFT));
ret_vec.push_back(ResizeRect(MoveRectEx(rc,x_off,y_off),HTBOTTOMRIGHT));
//上
rc = GenRect(border_width,0,x_off,border_width);
ret_vec.push_back(ResizeRect(rc,HTTOP));
ret_vec.push_back(ResizeRect(MoveRectEx(rc,0,y_off),HTBOTTOM));
//左
rc = GenRect(0,border_width,border_width,y_off);
ret_vec.push_back(ResizeRect(rc,HTLEFT));
ret_vec.push_back(ResizeRect(MoveRectEx(rc,x_off,0),HTRIGHT));
}
//系统按钮和icon 标题实现
struct SysButtons
{
CMyBtn *g_close_btn;
CMyBtn *g_min_btn;
CMyBtn *g_max_btn;
CMyIcon* g_icon;
int m_mouse_state;
BOOL m_bEnable;
void SetEnable(BOOL b)
{
m_bEnable = b;
}
BOOL isEnable()
{
return m_bEnable;
}
SysButtons()
{
m_bEnable = FALSE;
g_max_btn=NULL;
g_min_btn=NULL;
g_close_btn=NULL;
g_icon=NULL;
m_mouse_state = 0;
}
void Create(HWND wnd)
{
g_close_btn = new CMyCloseBtn();
g_close_btn->m_parent = wnd;
RECT rcWin;
GetClientRect(wnd,&rcWin);
g_close_btn->CorrectRect(rcWin);
g_min_btn = new CMyMinBtn();
g_min_btn->m_parent = wnd;
g_min_btn->CorrectRect(rcWin);
g_max_btn = new CMyMaxBtn();
g_max_btn->m_parent = wnd;
g_max_btn->CorrectRect(rcWin);
g_icon = new CMyIcon();
g_icon->CorrectRect(rcWin);
}
void OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_close_btn->OnLButtonUp(hWnd,wParam,lParam);
g_min_btn->OnLButtonUp(hWnd,wParam,lParam);
g_max_btn->OnLButtonUp(hWnd,wParam,lParam);
}
void OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
g_close_btn->OnLButtonDown(hWnd,wParam,lParam);
g_min_btn->OnLButtonDown(hWnd,wParam,lParam);
g_max_btn->OnLButtonDown(hWnd,wParam,lParam);
}
void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
if(m_mouse_state==0)
{
TRACKMOUSEEVENT te={sizeof(TRACKMOUSEEVENT ),TME_LEAVE,hWnd};
TrackMouseEvent(&te);
m_mouse_state = 1;
}
g_close_btn->OnMouseMove(hWnd,wParam,lParam);
g_min_btn->OnMouseMove(hWnd,wParam,lParam);
g_max_btn->OnMouseMove(hWnd,wParam,lParam);
}
void OnSize(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
CorrectBtns(hWnd);
}
void OnMouseLeave(HWND hWnd)
{
m_mouse_state = 0;
g_close_btn->OnMouseLeave(hWnd);
g_min_btn->OnMouseLeave(hWnd);
g_max_btn->OnMouseLeave(hWnd);
}
LRESULT OnNcHitTest(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
int x;
int y;
x = LOWORD(lParam);
y = HIWORD(lParam);
RECT rcWin;
GetClientRect(hWnd,&rcWin);
RECT rcTitle;
sys_frame_settings::get().GetTitleRect(rcWin,rcTitle);
POINT pt={x,y};
ScreenToClient(hWnd,&pt);
CheckAndRedraw(hWnd,pt);
if(PtInCaption(hWnd,wParam,lParam))
{
return HTCAPTION;
}
vector vec;
GenResizeRect(rcWin,vec);
for(size_t i=0;iPtInRect(pt))
{
g_min_btn->SetState(BTN_STATE_NORMAL);
if(g_min_btn->isChanged())
{
InvalidateRect(hWnd,&g_min_btn->m_rt,TRUE);
}
}
if(!g_max_btn->PtInRect(pt))
{
g_max_btn->SetState(BTN_STATE_NORMAL);
if(g_max_btn->isChanged())
{
InvalidateRect(hWnd,&g_max_btn->m_rt,TRUE);
}
}
if(!g_close_btn->PtInRect(pt))
{
g_close_btn->SetState(BTN_STATE_NORMAL);
if(g_close_btn->isChanged())
{
InvalidateRect(hWnd,&g_close_btn->m_rt,TRUE);
}
}
}
HRGN GenFromRect(RECT &rc)
{
return CreateRectRgn(rc.left,rc.top,rc.right,rc.bottom);
}
void CorrectBtns(HWND hWnd)
{
RECT rcWin;
GetClientRect(hWnd,&rcWin);
g_max_btn->CorrectRect(rcWin);
g_min_btn->CorrectRect(rcWin);
g_close_btn->CorrectRect(rcWin);
g_icon->CorrectRect(rcWin);
}
HRGN GetRgn(HWND hWnd)
{
CorrectBtns(hWnd);
HRGN rgnMax = GenFromRect(g_max_btn->m_rt);
HRGN rgnMin = GenFromRect(g_min_btn->m_rt);
HRGN rgnClose = GenFromRect(g_close_btn->m_rt);
CombineRgn(rgnMax,rgnMax,rgnMin,RGN_OR);
CombineRgn(rgnMax,rgnMax,rgnClose,RGN_OR);
DeleteObject(rgnMin);
DeleteObject(rgnClose);
return rgnMax;
}
void OnPaint(HWND hWnd,HDC hdc)
{
//绘制边框
RECT rcWin;
GetClientRect(hWnd,&rcWin);
HBRUSH br = CreateSolidBrush(sys_frame_settings::get().border_corlor);
for(int i=0; iDraw(hdc);
g_min_btn->Draw(hdc);
g_max_btn->Draw(hdc);
g_icon->Draw(hdc);
}
void SetMaximizeState(HWND hWnd)
{
g_max_btn->SetMaximizeState(hWnd);
}
BOOL PtInCaption(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
int x;
int y;
x = LOWORD(lParam);
y = HIWORD(lParam);
RECT rcWin;
GetClientRect(hWnd,&rcWin);
RECT rcTitle;
sys_frame_settings::get().GetTitleRect(rcWin,rcTitle);
POINT pt={x,y};
ScreenToClient(hWnd,&pt);
{
RECT rt = g_close_btn->m_rt;
WCHAR msg[256]={};
wsprintf(msg,L"%d,%d,(%d,%d)-(%d,%d)",pt.x,pt.y,rt.left,rt.top,rt.right,rt.bottom);
OutputDebugString(msg);
}
HRGN rgn = CreateRectRgn(rcTitle.left,rcTitle.top,rcTitle.right,rcTitle.bottom);
HRGN rgnSysBtns = GetRgn(hWnd);
int ret=CombineRgn(rgn,rgn,rgnSysBtns,RGN_DIFF);
if(ret!=NULLREGION && ret!=ERROR)
{
if(PtInRegion(rgn,pt.x,pt.y))
{
DeleteObject(rgn);
DeleteObject(rgnSysBtns);
return TRUE;
}
}
DeleteObject(rgn);
DeleteObject(rgnSysBtns);
return FALSE;
}
void OnNcLButtionDbClk(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
if(wParam == HTCAPTION)
{
SetMaximizeState(hWnd);
}
}
};
#endif
在这里调用类 CMyBtn 一些派生类 CMyMinBtn CMyIcon CMyMaxBtn CMyCloseBtn 实现按钮绘制和icon绘制
代码如下
#pragma once
/*
状态 : normal over down
显示 : 背景色,点阵数组,点阵颜色
*/
enum
{
BTN_STATE_NORMAL,
BTN_STATE_OVER,
BTN_STATE_DOWN
};
enum {
MAX_STATE_NORMAL,
MAX_STATE_MAXIZED,
};
enum {
MOUSE_STATE_OFF,
MOUSE_STATE_ON,
};
#include "win_settings.h"
inline int RECT_WIDTH(RECT &rc){return rc.right-rc.left;}
inline int RECT_HEIGHT(RECT &rc){return rc.bottom-rc.top;}
class CMyBtn
{
public:
CMyBtn(void);
~CMyBtn(void);
//
int m_state;
int m_old_state;
RECT m_rt;
HWND m_parent;
BOOL m_bDown;
void SetParent(HWND wnd)
{
m_parent = wnd;
}
void SetState(int state)
{
m_old_state = m_state;
m_state = state;
}
bool isChanged()
{
return m_state != m_old_state;
}
int GetState()
{
return m_state;
}
void SetDownFlag(BOOL b)
{
m_bDown = b;
}
bool PtInRect(POINT pt)
{
return ::PtInRect(&m_rt,pt)?true:false;
}
int GetMaximizeState()
{
return m_max_state;
}
void SetMaximizeState(HWND hWnd)
{
if(m_max_state==MAX_STATE_NORMAL)
{
PostMessage(hWnd,WM_SYSCOMMAND,SC_MAXIMIZE,0);
m_max_state = MAX_STATE_MAXIZED;
}
else
{
PostMessage(hWnd,WM_SYSCOMMAND,SC_RESTORE,0);
m_max_state = MAX_STATE_NORMAL;
}
}
void SetMinize(HWND hWnd)
{
PostMessage(hWnd,WM_SYSCOMMAND,SC_MINIMIZE,0);
}
virtual BOOL OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
int x;
int y;
x = LOWORD(lParam);
y = HIWORD(lParam);
POINT pt={x,y};
if(PtInRect(pt))
{
SetState(BTN_STATE_NORMAL);
InvalidateRect(hWnd,&m_rt,TRUE);
SetDownFlag(FALSE);
return TRUE;
}
return FALSE;
}
virtual void OnMouseLeave(HWND hWnd)
{
SetState(BTN_STATE_NORMAL);
InvalidateRect(hWnd,&m_rt,TRUE);
}
virtual void OnMouseMove(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
int x;
int y;
x = LOWORD(lParam);
y = HIWORD(lParam);
POINT pt={x,y};
if(PtInRect(pt))
{
SetState(BTN_STATE_OVER);
InvalidateRect(hWnd,&m_rt,TRUE);
}
else
{
SetState(BTN_STATE_NORMAL);
if(isChanged())
{
InvalidateRect(hWnd,&m_rt,TRUE);
}
}
}
virtual BOOL OnLButtonDown(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
int x;
int y;
x = LOWORD(lParam);
y = HIWORD(lParam);
POINT pt={x,y};
if(PtInRect(pt))
{
SetState(BTN_STATE_DOWN);
InvalidateRect(hWnd,&m_rt,TRUE);
SetDownFlag(TRUE);
return TRUE;
}
return FALSE;
}
virtual void CorrectRect(RECT &rcWin)
{
}
int m_max_state;
virtual void Draw(HDC hdc);
};
派生类
#pragma once
#include "mybtn.h"
class CMyMaxBtn :
public CMyBtn
{
public:
CMyMaxBtn(void);
~CMyMaxBtn(void);
virtual void Draw(HDC hdc);
virtual BOOL OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam);
virtual void CorrectRect(RECT &rcWin);
BYTE m_maxize_pic[100];
BYTE m_normal_pic[100];
};
#pragma once
#include "mybtn.h"
class CMyMinBtn :
public CMyBtn
{
public:
CMyMinBtn(void);
~CMyMinBtn(void);
virtual void Draw(HDC hdc);
virtual BOOL OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam);
virtual void CorrectRect(RECT &rcWin);
};
#pragma once
#include "mybtn.h"
class CMyCloseBtn :
public CMyBtn
{
public:
CMyCloseBtn(void);
~CMyCloseBtn(void);
virtual void Draw(HDC hdc);
virtual BOOL OnLButtonUp(HWND hWnd,WPARAM wParam,LPARAM lParam);
virtual void CorrectRect(RECT &rcWin);
unsigned char m_normal_pic[100];
};
还有一个总的setting 类,里面定义,窗口的背景色,边框颜色,边框宽度,字体等等
#ifndef _settings_h_
#define _settings_h_
//窗体的配置参数
//注意:边框过窄会导致窗口改变大小不方便
class sys_frame_settings
{
public:
sys_frame_settings()
{
border_corlor = RGB(128,128,128);
title_bk_color = RGB(2,167,240);
title_text_color= RGB(255,255,255);
title_height = 23;
border_width = 1;
}
static sys_frame_settings & get(){
static sys_frame_settings a;
return a;
}
void setWinRect(RECT &rt)
{
rcWin = rt;
}
void SetTitleRect(RECT &rt)
{
rcTitle = rt;
}
void GetTitleRect(RECT &rcWin,RECT &rcTitle)
{
rcTitle = rcWin;
InflateRect(&rcTitle,-1*border_width,-1*border_width);
rcTitle.bottom = rcTitle.top+title_height;
}
void GetCaptionRect(RECT &rcWin,RECT &ret_rt)
{
ret_rt = rcWin;
InflateRect(&ret_rt,-1*border_width,-1*border_width);
ret_rt.left = ret_rt.left+10+16;
ret_rt.bottom=ret_rt.top+title_height;
}
//边框色
COLORREF border_corlor;
//标题背景色
COLORREF title_bk_color;
//
COLORREF title_text_color;
//标题高度
int title_height;
//标题位置和大小
RECT rcTitle;
//窗口位置和大小
RECT rcWin;
//关闭按钮
RECT rcClose;
//最大化按钮
RECT rcMax;
//最小化按钮
RECT rcMin;
//边框宽度
int border_width;
};
#endif
此程序关键是如下的知识: