📄 mdichild.cpp
字号:
// MDIChild.cpp: implementation of the CMDIChild class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include "SDI.h"
#include "MDIChild.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//PMDICHILD m_pMDIChild = NULL; // 窗口的 CLASSXP 结构指针
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
PMDICHILD CMDIChild::m_pMDIChild = NULL;
CMDIChild::CMDIChild()
{
}
CMDIChild::~CMDIChild()
{
}
//把子窗口加入,管理链表
int CMDIChild::ADD(CView *pView, LPCSTR lpName, UINT nType)
//int CMDIChild::ADD(UINT nID, CWND *pView, LPCSTR lpName, UINT nType)
{
PMDICHILD pChild, pParent;
HWND hWnd;
pParent=GetClassParent(); //取出父窗口
if(!pParent) return -2;
pChild = GetClassChild(lpName);
if(!pChild) //新建
{
if(pView==NULL)return -1; //不能新增空窗口
// 分配存储空间,增加一个节点
hWnd = pView->GetSafeHwnd();
pChild = (PMDICHILD) new MDICHILD;
memset(pChild,0, sizeof(MDICHILD));
if(!pChild) return -1;
pChild->pNext = (PMDICHILD)m_pMDIChild;
m_pMDIChild = pChild;
pChild->hView = hWnd;
pChild->hParent = pParent->hView;
memcpy(pChild->szName,lpName, MDI_MAXNAME);
pChild->wpPrev = (WNDPROC )SetWindowLong(hWnd,GWL_WNDPROC,(LONG)MDIChildProc);
if(!pChild->wpPrev) //失败
{
DelClassChild(pChild->hView);
return -3;
}
DrawTitle(pParent->hView);
pView->CenterWindow();
pView->ShowWindow(nType);
SetActive(pChild->hView, NULL, MDI_AC_STAND); //设置表链状态
return 0;
}
if(pChild->hView != pParent->pData->hViewActive)
{
SetActive(pChild->hView, NULL, MDI_AC_STAND);
SetWindowPos(pChild->hView, NULL,0,0,0,0,
SWP_NOSIZE|SWP_NOREPOSITION|SWP_SHOWWINDOW|
SWP_NOMOVE);
}
return 1;
}
//把子窗口从管理链表中删除
//把子窗口从管理链表中删除
BOOL CMDIChild::DelClassChild(CWnd *pWnd)
{
return DelClassChild(pWnd->GetSafeHwnd());
}
BOOL CMDIChild::DelClassChild(HWND hWnd)
{
PMDICHILD pChild, pDel = NULL, pParent;
// 循环查找待删除节点的上一个节点
pDel = GetClassChild(hWnd);
// 获取待删除的节点指针
if (pDel != NULL)
{
// 如果待删除的节点就是 m_pMDIChild 节点
if(pDel->hParent==NULL)return FALSE; //禁止删除父窗口
if (pDel == m_pMDIChild)
{
m_pMDIChild = pDel->pNext;
pChild = pDel->pNext;
}
else
{
// 循环查找待删除节点的上一个节点
for (pChild = (PMDICHILD)m_pMDIChild; pChild != NULL; pChild = pChild->pNext)
{
// 如果找到
if (pChild->pNext == pDel)
{
// 使链表跳过待删除的节点
pChild->pNext = pDel->pNext;
break;
}
}
}
// 取消窗口子类化并重画窗口
SetWindowLong(hWnd, GWL_WNDPROC, (LONG) pDel->wpPrev);
// 删除堆内存
if(pDel->pData) delete pDel->pData;
delete pDel;
pParent = GetClassParent();
if(pParent)
SetActive(pParent->pData->hViewPre, NULL, MDI_AC_FRUSHNEW|
MDI_AC_SETOLD|MDI_AC_SETNEW); //激活其它子窗口
return TRUE;
}
return FALSE;
}
//子窗口信息
LRESULT CALLBACK CMDIChild::MDIChildProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lReturn;
PMDICHILD pChild, pParent;
PMDIDATA pData = NULL;
POINTS point;
// RECT Rect;
LPMINMAXINFO lpmmi;
UINT umessage = uMsg;
pChild = (PMDICHILD)GetClassChild(hWnd);
if (!pChild) return 0;
pParent =(PMDICHILD)GetClassParent();
if(pParent) pData = pParent->pData;
if(pParent && pData)
{
switch(uMsg)
{//限制最大化的位置
case WM_GETMINMAXINFO:
lpmmi = (LPMINMAXINFO) lParam;
lpmmi->ptMaxPosition.x =pData->rcMaxSize.left;
lpmmi->ptMaxPosition.y =pData->rcMaxSize.top;
lpmmi->ptMaxSize.x = pData->rcMaxSize.right-pData->rcMaxSize.left;
lpmmi->ptMaxSize.y = pData->rcMaxSize.bottom-pData->rcMaxSize.top;
break;
case WM_NCLBUTTONDOWN :
if (wParam == HTCAPTION)
{
if(IsZoomed(hWnd))
{
return 0;
}
}
break;
//计算含边框下的位移
case WM_MOVE: //限制移动区域
point.x = (int)(short) LOWORD(lParam); // horizontal position
point.y = (int)(short) HIWORD(lParam); // vertical position
point.y = point.y - GetSystemMetrics(SM_CYDLGFRAME)-
GetSystemMetrics(SM_CYBORDER) -
GetSystemMetrics(SM_CYCAPTION);
point.x -= GetSystemMetrics(SM_CXDLGFRAME);
if (point.y < pData->rcMaxSize.top)//限制顶部
{
SetWindowPos (hWnd,NULL, point.x, pData->rcMaxSize.top,
0 , 0,
SWP_NOSIZE|SWP_NOZORDER);
return 0;
}
break;
case WM_ACTIVATEAPP://跳转到其它程式时
DrawTitle(pParent->hView, wParam);
return 0;
case WM_ACTIVATE:
if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
{//子窗口激活处理
if(pData->hViewActive != hWnd) //发生改变
{
pData->hViewPre = pData->hViewActive;
pData->hViewActive = hWnd;
DrawTitle(pData->hViewPre, FALSE);
break;
}
DrawTitle(hWnd);
return 0;
}
else
{//子窗口禁止激活
if(pParent->hView == (HWND)lParam) //跳转到主窗口
{
DrawTitle(hWnd);
return 0;
}
}
break;
}
}
lReturn = (LONG)CallWindowProc(pChild->wpPrev, hWnd, uMsg, wParam, lParam);
if (umessage == WM_NCDESTROY) //窗口消毁时,自动删除表链
{
SetActive(pData->hViewPre, NULL, MDI_AC_FRUSHNEW|
MDI_AC_SETOLD|MDI_AC_SETNEW); //激活其它子窗口
//DrawTitle(pData->hViewPre);
DelClassChild(pChild->hView);
}
return lReturn;
}
//主窗口信息
LRESULT CALLBACK CMDIChild::MDIMainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lReturn;
PMDICHILD pChild, pParent;
PMDIDATA pData = NULL;
pParent =(PMDICHILD)GetClassParent();
if(!pParent)
return 0;
else
pData = pParent->pData;
if(pData)
{
switch(uMsg)
{
//禁止改变窗口大小,只可以最小化和最大化
case WM_NCLBUTTONDBLCLK :
case WM_NCRBUTTONDBLCLK :
lReturn = SendMessage(hWnd, WM_NCHITTEST, 0, lParam);
if(lReturn==HTCAPTION || lReturn==HTSYSMENU)return 0;
break;
case WM_NCLBUTTONDOWN :
case WM_NCRBUTTONDOWN :
lReturn = SendMessage(hWnd, WM_NCHITTEST, 0, lParam);
if(lReturn==HTSYSMENU||lReturn==HTZOOM || lReturn==HTMAXBUTTON)return 0;
break;
case WM_ACTIVATE:
if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
{//主窗口激活
//SendMessage(pData->hViewActive, WM_ACTIVATE,WA_CLICKACTIVE,0);
DrawTitle(pData->hViewActive); //激活子窗口
return 0;
}
else
{//主窗口禁止激活
pChild = GetClassChild((HWND)lParam);
if(pChild) //转到子窗口
{
DrawTitle(hWnd);
return 0;
}
else //重绘子窗口
{
DrawTitle(pData->hViewActive,FALSE);
}
}
break;
}//end switch
}//end if
lReturn = (LONG)CallWindowProc(pParent->wpPrev, hWnd, uMsg, wParam, lParam);
if (uMsg == WM_NCDESTROY) //窗口消毁时,自动删除表链
DelClassChild(pParent->hView);
return lReturn;
}
//取子窗口
PMDICHILD CMDIChild::GetClassChild(HWND hWnd)
{
PMDICHILD pChild;
// 循环查找待删除节点的上一个节点
for (pChild = (PMDICHILD)m_pMDIChild; pChild != NULL; pChild=pChild->pNext)
if (pChild->hView == hWnd)
return pChild;
return NULL;
}
//取子窗口
PMDICHILD CMDIChild::GetClassChild(LPCSTR lpName)
{
PMDICHILD pChild;
// 循环查找待删除节点的上一个节点
for (pChild = (PMDICHILD)m_pMDIChild; pChild != NULL; pChild=pChild->pNext)
{
if((memcmp(pChild->szName,lpName, MDI_MAXNAME))==0)
return pChild;
}
return NULL;
}
//取父窗口
PMDICHILD CMDIChild::GetClassParent()
{
PMDICHILD pChild;
// 循环查找待删除节点的上一个节点
for (pChild = (PMDICHILD)m_pMDIChild; pChild != NULL; pChild=pChild->pNext)
if (pChild->hParent == NULL)
return pChild;
return NULL;
}
//初期化父窗口,只有父窗口的hParent=NULL
//pRect是子窗口的活动区域FOR Screen
//还没实现限制子窗口的活动区域
int CMDIChild::InitMainWnd(CWnd *pWnd, RECT *pRect)
{
PMDICHILD pChild;
PMDIDATA pData;
RECT RectDef;
POINT point;
HWND hWnd;
if(pWnd==NULL)return -1;
hWnd = pWnd->GetSafeHwnd();
if(GetClassChild(hWnd)) return 1;
//显示最大化
if(!pWnd->IsZoomed())
pWnd->ShowWindow(SW_MAXIMIZE);
//除去最大化按钮
// pWnd->ModifyStyle(WS_MAXIMIZEBOX,NULL);
//设置活动区域
if(pRect==NULL)
{
pWnd->GetClientRect(&RectDef);
point.x = 0; point.y = 0;
ClientToScreen(hWnd, &point);
RectDef.left += point.x; RectDef.top += point.y;
RectDef.right += point.x; RectDef.bottom += point.y;
pRect = &RectDef;
}
//新建,分配存储空间,增加一个节点
pData = (PMDIDATA) new MDIDATA;
memset(pData,0, sizeof(MDIDATA));
if(!pData) return -1;
pChild = (PMDICHILD) new MDICHILD;
memset(pChild,0, sizeof(MDICHILD));
if(!pChild) {delete pData; return -1;}
pChild->pNext = (PMDICHILD)m_pMDIChild;
m_pMDIChild = pChild;
pChild->hView = hWnd;
pChild->hParent = NULL;
pChild->wpPrev = (WNDPROC )SetWindowLong(hWnd,GWL_WNDPROC,(LONG)MDIMainProc);
if (!pChild->wpPrev) //安装失败
{
delete m_pMDIChild->pData;
delete m_pMDIChild;
m_pMDIChild = NULL;
return -1;
}
pChild->pData = pData;
SetRect(&pData->rcMaxSize,pRect->left,pRect->top,
pRect->right ,pRect->bottom);
return 0;
}
//删除
BOOL CMDIChild::UninitMainWnd(void)
{
return TRUE;
}
//设置子窗口活动区域
BOOL CMDIChild::SetActiveRect(RECT *pRect)
{
PMDICHILD pParent;
pParent=GetClassParent(); //取出父窗口
if(!pParent) return FALSE;
SetRect(&pParent->pData->rcMaxSize,
pRect->left , pRect->top,
pRect->right, pRect->bottom);
return FALSE;
}
//管理活动窗口表链
void CMDIChild::SetActive(HWND hNew, HWND hOld, UINT nType)
{
PMDICHILD pParent;
pParent=GetClassParent(); //取出父窗口
if(!pParent) return ;
if(nType & MDI_AC_RESTOREOLD)
pParent->pData->hViewPre = pParent->pData->hViewActive;
if(nType & MDI_AC_SETOLD)
pParent->pData->hViewPre = hOld;
if(nType & MDI_AC_SETNEW)
pParent->pData->hViewActive = hNew;
if(nType & MDI_AC_FRUSHOLD)
SendMessage(pParent->pData->hViewPre, WM_NCACTIVATE,FALSE,0);
if(nType & MDI_AC_FRUSHNEW)
DrawTitle(hNew);
// SendMessage(hNew, WM_NCACTIVATE,TRUE,0);
}
//重绘窗口标题栏
LRESULT CMDIChild::DrawTitle(HWND hWnd, BOOL bActive)
{
return SendMessage(hWnd, WM_NCACTIVATE,bActive,0);
// return SendMessage(hWnd, WM_NCPAINT,1,0);
// return SendMessage(hWnd, WM_NCACTIVATE,bActive,0);
}
//在主窗口OnPreCreateWindow()中设置窗口为最大化
void CMDIChild::SetOnPreCreateWindow(CREATESTRUCT *cs)
{
/* cs->style &= ~WS_MAXIMIZEBOX; //除去最大化按钮
cs->x = 0;
cs->y = 0;
cs->cx=GetSystemMetrics(SM_CXSCREEN/2);
//225等于窗口最大化且满屏
cs->cy=GetSystemMetrics(SM_CYSCREEN/2)-225;
*/
}
//重排所有子窗口
void CMDIChild::InitialUpdateFrame()
{
PMDICHILD pChild;
PMDICHILD pParent;
RECT *pRect;
pParent=GetClassParent(); //取出父窗口
if(!pParent) return ;
HWND hActive = pParent->pData->hViewActive;
pRect = &pParent->pData->rcMaxSize;
for (pChild = (PMDICHILD)m_pMDIChild; pChild != NULL; pChild=pChild->pNext)
{
if (pChild->hParent && pChild->hView != hActive)
{
SetWindowPos(pChild->hView, NULL,
pRect->left,pRect->top,0,0,
SWP_NOSIZE|SWP_NOREPOSITION|SWP_SHOWWINDOW);
// ShowWindow(pChild->hView, SW_SHOW);
}
}
if(hActive)
{
SetWindowPos(hActive, NULL,
pRect->left,pRect->top,0,0,
SWP_NOSIZE|SWP_NOREPOSITION|SWP_SHOWWINDOW);
// ShowWindow(hActive, SW_SHOW);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -