应用小窗口化,窗口化应用程序

  应用小窗口化,窗口化应用程序

  所谓窗口子类化:改变一个已经存在的窗口实例的性质:消息处理与其他实例属性。

  通常在软件开发工具包(软件开发工具包)中所谓的窗口子类化就是改变一个窗口函数(如GetWindowLong()和SetWindowLong())通过这两个函数来设置窗口的属性等;

  而今天我们主要内容是介绍MS-VisualC++的类库(微软基础班的缩写)中的子类化,它跟软件开发工具包(软件开发工具包)中的子类化不太一样:

  所有MS-VisualC++的类库(微软基础班的缩写)窗口有相同的窗口函数,由该窗口函数根据窗口句柄查找窗口实例,在把消息映射到该窗口类(类别)得消息处理函数上。为了利用MS-VisualC++的类库(微软基础班的缩写)的消息映射机制,不宜改变窗口函数(名),MFC也把子类化封装在函数子类窗口()中。

  #include Subclass.h

  classCSubclassWnd:公共对象{

  公共:

  DECLARE _ DYNAMIC(CSubclassWnd);

  CSubclassWnd();

  ~ CSubclassWnd();

  //子类化一个窗口钩子(空)到脱钩(在WM_NCDESTROY上自动)

  虚拟BOOLHookWindow(HWNDhwnd);

  虚拟BOOLHookWindow(CWnd * pWnd){返回挂钩窗口(pWnd-GetSafeHwnd());}

  虚拟boolishoked(){ return m _ hWnd!=NULL}

  朋友结果回调HookWndProc(HWND,UINT,WPARAM,LPARAM);

  友类CSubclassWndMap

  #ifdef _DEBUG

  虚拟void AssertValid()常量;

  虚拟void Dump(CDumpContext dc)常量;

  #endif

  受保护:

  HWNDm _ hWnd//窗口被钩住

  WNDPROCm _ pOldWndProc//.和原始窗口进程

  CSubclassWnd * m _ pNext//此窗口挂钩链中的下一个

  //重写此方法以在特定的处理程序中处理消息

  虚拟LRESULT WindowProc(UINT msg,WPARAM wp,LPARAM LP);

  虚拟LRESULT Default();//在处理程序小脑顶核电刺激的末尾调用这个函数

  };

  #include Subclass.cpp

  CSubclassWnd:CSubclassWnd()

  {

  m _ pNext=NULL

  m _ pOldWndProc=NULL

  m _ hWnd=NULL

  }

  CSubclassWnd:~CSubclassWnd()

  {

  if (m_hWnd)

  钩子窗口((HWND)NULL);//解除窗口挂钩

  }

  //////////////////

  //挂钩一个窗口。

  //这会安装一个新的窗口过程,将消息定向到CSubclassWnd .

  //pWnd=NULL以移除。

  //

  BOOL CSubclassWnd:HookWindow

  {

  ASSERT _ VALID(this);

  if (hwnd) {

  //挂钩窗口

  ASSERT(m _ hWnd==NULL);

  ASSERT(:is窗口(hwnd));

  地图。添加(hwnd,这个);//添加到挂钩地图

  } else if (m_hWnd) {

  //解开窗口

  地图。去掉(这个);//从地图中移除

  m _ pOldWndProc=NULL

  }

  m _ hWnd=hwnd

  返回真实的

  }

  //////////////////

  //窗口类似过程的虚函数

  //覆盖来做事情违约将消息传递给下一个钩子;

  //最后一个钩子将消息传递给原始窗口。

  //如果您想要真正的

  //窗口来获取消息。这就像CWnd:WindowProc,除了

  //CSubclassWnd不是窗口。

  //

  LRESULT CSubclassWnd:窗口进程(UINT msg,WPARAM wp,LPARAM lp)

  {

  //ASSERT _ VALID(this);//因速度原因而移除

  ASSERT(m _ pOldWndProc);

  返回m_pNext?m_pNext- WindowProc(msg,wp,lp):

  * CallWindowProc(m _ pOldWndProc,m_hWnd,msg,wp,LP);

  }

  //////////////////

  //像调用基类WindowProc但是不带参数,所以个性

  //消息处理程序可以做默认的事情。像CWnd:默认值

  //

  LRESULT CSubclassWnd:Default()

  {

  //MFC在线程状态中存储当前消息

  MSG curMsg=AfxGetThreadState()-m _ lastSentMsg;

  //注意:必须显式调用CSubclassWnd:WindowProc以避免不限制

  //虚函数上的递归

  返回CSubclassWnd:窗口过程(curmsg。消息,curMsg.wParam,curMsg。lparam);

  }

  #ifdef _DEBUG

  void CSubclassWnd:assert valid()const

  {

  CObject:assert valid();

  ASSERT(m _ hWnd==NULL :is window(m _ hWnd));

  if (m_hWnd) {

  for (CSubclassWnd* p=theHookMap .lookup(m _ hWnd);p;p=p- m_pNext) {

  如果(p==这个)

  打破;

  }

  断言(p);//应该已经找到了!

  }

  }

  void CSubclassWnd:Dump(CDumpContext DC)常量

  {

  CObject:Dump(DC);

  }

  #endif

  //////////////////

  //消息挂钩的子类窗口过程。取代AfxWndProc(或其他

  //否则之前在。)

  //

  LRESULT回调

  HookWndProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)

  {

  #ifdef _USRDLL

  //如果这是一个DLL,需要设置MS-VisualC++的类库(Microsoft Foundation Class的缩写)状态

  AFX _ MANAGE _ STATE(AfxGetStaticModuleState());

  #endif

  //设置MS-VisualC++的类库(Microsoft Foundation Class的缩写)消息状态,以防有人需要它

  //这就像AfxCallWindowProc一样,但是我们不能使用它,因为

  //CSubclassWnd不是CWnd .

  //

  MSG curMsg=AfxGetThreadState()-m _ lastSentMsg;

  MSGoldMsg=curMsg//保存以便嵌套

  curMsg.hwnd=hwnd

  curMsg.message=msg

  curMsg.wParam=wp

  curMsg.lParam=lp

  //获取此窗口的挂钩对象。从挂钩地图获取

  CSubclassWnd * pSubclassWnd=theHookMap .查找(hwnd);

  ASSERT(pSubclassWnd);

  lr结果lr

  if (msg==WM_NCDESTROY) {

  //窗口正在被破坏:解开所有挂钩(对于此窗口)

  //并将消息传递给原始窗口进程

  //

  WNDPROC WNDPROC=pSubclassWnd-m _ pOldWndProc;

  地图移除所有(hwnd);

  lr=:CallWindowProc(wndproc,hwnd,msg,wp,LP);

  }否则{

  //传递给消息挂钩

  lr=pSubclassWnd- WindowProc(msg,wp,LP);

  }

  curMsg=oldMsg//弹出状态

  返回lr;

  }

  这边只是介绍子类窗口()内部实现方式。

  CSubclassWnd类的作用是不用派生新类便能在MS-VisualC++的类库(微软基础班的缩写)中子类化窗口。

  现在我们这边只提CSubclass Wnd类的一个作用,其实CSubclass Wnd也经常被说成是万能类,可以用在很多的界面和控件上。

  具体实例:

  以美图秀秀的弹出对话框自定义皮肤为例:

  创建一个自定义皮肤类:

  类CDlgSkin:公共CSubclassWnd

  {

  公共:

  自定义变量

  CDlgSkin();

  CDlgSkin(LPCTSTR skinfile)

  {

  CDlgSkin();

  LoadSkin(皮肤文件);

  }

  virtual ~ CDlgSkin();

  BOOL InitSkinWin(CString strPath,CWnd * wnd);

  虚拟LRESULT WindowProc(UINT msg,WPARAM wparam,LPARAM LPARAM);

  ……

  ……

  }

  //初始化

  BOOL CDlgSkinWin:安装皮肤(CWnd * wnd)

  {

  如果(!wnd !m_bInit)

  返回错误的

  //开始捕获此窗口的消息

  //钩子窗口((HWND)NULL);

  int r=挂钩窗口(wnd);

  return r;

  }

  //消息处理函数

  LRESULT CDlgSkin:window proc(UINT msg,WPARAM wp/*wparam*/,LPARAM lp/*lparam*/)

  {

  如果(!IsWindow(m_hWnd))

  返回0;

  如果(!m_bInit)

  返回默认值();

  开关(消息)

  {

  案例WM_SHOWWINDOW:

  //当窗口句柄为对话框时,调用设置和获取窗口位置强制OnNcCalcSize

  中频(可湿性粉剂)

  SetWindowPos( m_hWnd,0,0,0,400,400,SWP _诺西泽SWP诺莫夫 SWP _帧已更改);

  默认();

  m _ down hittest=0;

  m _ move hittest=0;

  返回0;

  打破;

  //case WM_ERASEBKGND:

  案例WM_INITMENUPOPUP:

  默认();

  返回0;

  案例WM_SYSCOMMAND:

  OnSysCommand( wp,LP);

  返回0;

  案例WM_SETTEXT:

  return OnSetText( wp,LP);

  案例WM_NCPAINT:

  OnNcPaint((HRGN)WP);

  返回0;

  案例WM_NCCALCSIZE:

  OnNcCalcSize( (BOOL)wp,(NCCALCSIZE _ PARAMS *)LP);

  返回0;

  案例WM_SIZE:

  OnSize( wp,low word(LP),hi word(LP));

  返回0;

  案例WM _激活:

  返回OnNcActivate((BOOL)WP);

  案例WM_NCHITTEST:

  return OnNcHitTest(c point(LOWORD(LP),hi word(LP)));

  案例WM_NCLBUTTONUP:

  OnNcLButtonUp(wp,CPoint(LOWORD(lp),hi word(LP)));

  返回0;

  案例WM_NCLBUTTONDOWN:

  OnNcLButtonDown(wp,CPoint(LOWORD(lp),hi word(LP)));

  返回0;

  案例WM_NCLBUTTONDBLCLK:

  OnNcLButtonDblClk(wp,c point(low word(LP),hi word(LP));

  返回0;

  案例WM_NCRBUTTONUP:

  OnNcRButtonUp(wp,CPoint(LOWORD(lp),hi word(LP)));

  返回0;

  案例WM_NCRBUTTONDOWN:

  OnNcRButtonDown(wp,CPoint(LOWORD(lp),hi word(LP)));

  返回0;

  案例WM_NCMOUSEMOVE:

  OnNcMouseMove( wp,CPoint(LOWORD(lp),hi word(LP)));

  返回0;

  案例WM_GETMINMAXINFO:

  OnGetMinMaxInfo((MINMAXINFO *)LP);

  返回0;

  案例WM_WINDOWPOSCHANGING:

  OnWindowPosChanging((WINDOWPOS *)LP);

  返回0;

  案例WM_SIZING:

  OnSizing( wp,(LPRECT)LP);

  返回0;

  案例WM_ACTIVATE:

  OnActivate( wp,CWnd:FromHandle((HWND)lp),0);

  返回0;

  案例WM _命令:

  如果(!HandleSysCommand( wp,lp))

  默认();

  返回0;

  默认值:

  返回默认值();

  }

  }

  简单的调用方法:

  B类:公共A

  {

  ……

  }

  一个

  电子商务

  HWND ha=a . GetSafeHwnd();

  b .子类窗口(ha);#当然A和B不一定是继承关系。

  注意:在被子类化的窗口销毁之前,必须执行窗口的反子类化:

  b.UnSubclassWindow();

  子类化跟超类化的区别:

  超类化:首先获得一个已存在的窗口类,然后设置窗口类,最后注册该窗口类。

  如:

  WNDCLASSEX wc

  WC . CB size=sizeof(WC);//由//Windows用于版本检查,不考虑窗口特征。

  GetClassInfoEx(hinst," XXXXXX ",WC);

  //hinst—定义窗口类XXXXXX的模块的句柄,比如系统定义的窗口类(如EDIT,BUTTON),hinst=NULL。

  WC . lpsz class name=" yyyyyy ";//必须更改窗口类的名称

  WC . hbrbackground=CreateSolidBrush(RGB(0,0.0));//更改背景画笔

  wc.lpfnWndProc=NewWndProc//改变窗口功能

  ……

  register classex(WC);//注册新的窗口类

  //使用窗口类

  ……

  * create window(_ T(" YYYYYYYY ",……);

  因此,超分类只能改变自己创建的窗口的特性,而不能用于创建的窗口;

  但是,子类化是在实例级别。只要能得到窗口的句柄,就可以子类化,这也是子类化比超类化的一个优势。

  摘要

  (0)子类化窗口过程函数,超类化窗口类(新窗口类名)

  (1)子类化在窗口实例级别,超类化在窗口类(WNDCLASS)级别。

  (2)超分类比子类化能完成更复杂的功能。在SDK类别中,子类化可以被认为是超分类的子集。

  (3)子类化只能改变窗口创建后的性质,但在窗口创建过程中不能做任何事情(ON_CREATE事件不能被拦截),而超类化可以实现;超分类不能用于创建的窗口,但子类化可以。

  来自:http://blog . . net/Lin _ angle/article/details/6178351

应用小窗口化,窗口化应用程序