windows 实现一个简单的自绘边框,具有最大化,最小化,icon,标题

您所在的位置:网站首页 画边框简单 windows 实现一个简单的自绘边框,具有最大化,最小化,icon,标题

windows 实现一个简单的自绘边框,具有最大化,最小化,icon,标题

2024-07-12 03:40| 来源: 网络整理| 查看: 265

实现一个简单的自绘边框,具有最大化,最小化,icon,标题. 当用户嫌windows的框架颜色不好看,要修改窗口的框架,就自己在win32上实现它,因为内容是使用cef框架实现,使用duilib 等界面库和cef的demo代码兼容性有些问题.

实现效果: 自绘窗体示例图片

设计 1 popup 窗口,overlapped 窗口有标题,菜单,一些限制2 定义客户区和非客户区 目的是在不同的区域返回不同的标志 。主要在 WM_NCHITTEST 中处理 分为: 1 标题区,去掉 最大,最小,关闭 三个按钮的上面 20-30 px 的区域,可以拖动窗口 2 左上右上左下右下,上,下 左 右 ,这些区域都支持拉伸 3 客户区,除去这些地方3 处理 WM_LBUTTONDOW WM_LBUTTONUP WM_MOUSEMOVE WM_MOUSELEAVE4 处理 WM_NCLBUTTONDBCLK 双击最大化,最小化5 绘制窗口 处理 WM_PAINT6 处理 WM_SIZE7 实现按钮类8 实现一个icon 类9 实现窗口的setting类10 实现窗口管理类 设计完成之后,实现

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

此程序关键是如下的知识:

窗体的知识: 客户区非客户区鼠标消息处理区域绘画窗口的一些基础知识,窗口类,注册,创建。c++一些知识


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3