窗口是屏幕
上的一个矩形区域
.窗口
分为3种
:覆盖窗口,弹窗和子窗口
.每个窗口
都有由系统绘画的"非客户区"
和应用绘画的"客户区"
.
在MFC
中,CWnd
类为各种窗口
提供了基类
.
1,通过窗柄
取得CWnd
指针
可调用Cwnd::FromHandle
函数,通过窗柄
取得Cwnd
指针.
void CDemoDlg::OnButton1()
{
HWND hWnd = GetSafeHwnd();
//取得当前窗口的句柄
CWnd* pWnd = CWnd::FromHandle(hWnd);
//通过`窗柄`取得`CWnd`指针
CString strText = _T("");
strText.Format("pWnd=0x%X\nthis=0x%X\n",pWnd,this);
AfxMessageBox(strText);
}
2,取得应用主窗口的指针
在CWinThread::m_pMainWnd
中保存主窗口指针
.可首先调用AfxGetApp
函数取得应用的指针
,然后通过应用指针
取得主窗口的指针
.
void CDemoDlg::OnButton2()
{
CDemoApp* pApp = (CDemoApp*)AfxGetApp();
//取得应用指针
CWnd* pMainWnd = pApp->m_pMainWnd;
//取得主窗口指针
CString strText = _T("");
strText.Format("pMainWnd=0x%X\nthis=0x%X\n",pMainWnd,this);
AfxMessageBox(strText);
}
3,取得指定点的窗口
可调用CWnd::WindowFromPoint
函数,取得指定点的窗口
.
a,在CDemoDlg
类中重载CWnd::PreTranslateMessage
函数.
BOOL CDemoDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_MOUSEMOVE)
{
CPoint point(LOWORD(pMsg->lParam),HIWORD(pMsg->lParam));
::ClientToScreen(pMsg->hwnd, &point);
//按屏幕坐标转换客户区坐标
OnMouseMove(0,point);
}
return CDialog::PreTranslateMessage(pMsg);
}
b,在CDemoDlg
类中添加WM_MOUSEMOVE
消息处理函数.
void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd* pWnd = WindowFromPoint(point);
//取得指定点的窗口
if (pWnd != NULL)
{
TRACE("%d\n",pWnd);
if (IsChild(pWnd))
{
CString strText = _T("");
pWnd->GetWindowText(strText);
SetWindowText(strText);
}
}
CDialog::OnMouseMove(nFlags, point);
}
4,最大化和最小化窗口
可调用CWnd::SendMessage
函数发送最大化或最小化窗口消息
,来最大化和最小化窗口
.
LRESULT SendMessage(
UINT message,
//发送的消息,值为`WM_SYSCOMMAND`时表示`系统命令消息`.
WPARAM wParam = 0,
//当`消息`值为`WM_SYSCMMAND`,参数`字参`值为`SC_MAXIMIZE,SC_MINIMIZE`,
LPARAM lParam = 0 );
//`SC_RESTORE`时分别表示`最大化窗口,最小化窗口,恢复窗口`.
void CDemoDlg::OnButton3()
{
//最大化窗口
SendMessage(WM_SYSCOMMAND,SC_MAXIMIZE,0);
}
void CDemoDlg::OnButton4()
{
//最小化窗口
SendMessage(WM_SYSCOMMAND,SC_MINIMIZE,0);
}
void CDemoDlg::OnButton5()
{
//恢复窗口
SendMessage(WM_SYSCOMMAND,SC_RESTORE,0);
}
5关闭窗口
可调用CWnd::SendMessage
函数,发送WM_CLOSE
消息来关闭窗口
.框架
调用CWnd::OnClose
函数处理WM_CLOSE
消息.
默认,OnClose
调用函数CWnd::DestroyWindow
函数来关闭窗口
.
void CDemoDlg::OnButton6()
{
//关闭窗口
SendMessage(WM_CLOSE,0,0);
}
void CDemoDlg::OnClose()
//添加`WM_CLOSE`消息处理函数
{
//判断是否关闭
if (IDYES == MessageBox(_T("是否关闭窗口?"),NULL,MB_YESNO))
{
CDialog::OnClose();
}
}
6设置窗口的大小和位置
可通过两个方法
设置窗口大小和位置
:1
.调用CWnd::SetWindowPos
函数;2
.调用CWnd::MoveWindow
函数.
void CDemoDlg::OnButton7()
{
//设置窗口的大小和位置
SetWindowPos(NULL,0,0,320,200,SWP_NOZORDER);
}
void CDemoDlg::OnButton8()
{
//设置窗口的大小和位置
MoveWindow(0,200,200,320);
}
7居中显示窗口
可调用CWnd::CenterWindow
函数居中显示窗口
.
void CDemoDlg::OnButton9()
{
//居中显示窗口
CenterWindow();
}
8顶层显示窗口
可调用CWnd::SetWindowPos
函数顶层显示窗口
,按最顶层
设置对话框窗口的层次
.
void CDemoDlg::OnButton10()
{
//设置窗口层次
SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE);
//`SWP_NOSIZE`:表示窗口保持当前的大小,`SWP_NOMOVE`:表示窗口保持当前的位置
}
9设置窗口图标
首先调用CWinApp::LoadIcon
函数加载图标资源
,然后调用CWnd::SetIcon
函数设置图标
.
void CDemoDlg::OnButton11()
{
//加载图标
HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON);
//设置图标
SetIcon(hIcon,FALSE);
//`假`:设置程序小图标,`真`:设置任务栏大图标
}
10
取得和设置窗口的标题
可分别调用CWnd::GetWindowText
和CWnd::SetWindowText
函数,取得和设置窗口标题
.
void CDemoDlg::OnButton12()
{
CString strText = _T("");
GetWindowText(strText);
//取得窗口标题
SetDlgItemText(IDC_TEXT,strText);
//设置编辑框文本
}
void CDemoDlg::OnButton13()
{
CString strText = _T("");
GetDlgItemText(IDC_TEXT,strText);
//取得编辑框文本
SetWindowText(strText);
//设置窗口标题
}
11
显示或隐藏窗口的标题栏
可调用CWnd::ModifyStyle
函数显示或隐藏窗口的标题栏
.
void CDemoDlg::OnButton14()
{
//删除标题栏风格
ModifyStyle(WS_CAPTION,0,SWP_FRAMECHANGED);
}
void CDemoDlg::OnButton15()
{
//添加标题栏风格
ModifyStyle(0,WS_CAPTION,SWP_FRAMECHANGED);
}
12
改变窗口形状
标准窗口
的形状
是矩形
的.要改变窗口的形状
,首先调用CRgn
类的成员函数创建相应形状的区域
,然后调用CWnd::SetWindowRgn
函数按窗口区域
设置它.
可分别用CRgn
类的CreateRectRgn,CreateEllipticRgn,CreatePolygonRgn
和CreateRoundRectRgn
函数来创建矩形,椭圆形,多边形和圆矩形区域
.
void CDemoDlg::OnButton16()
{
CRect rect;
GetClientRect(rect);
//创建矩形区域
CRgn rgn;
rgn.CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom);
//设置窗口的区域
SetWindowRgn((HRGN)rgn,TRUE);
}
void CDemoDlg::OnButton17()
{
CRect rect;
GetClientRect(rect);
//创建椭圆形区域
CRgn rgn;
rgn.CreateEllipticRgn(0,0,rect.Width(),rect.Height());
//设置窗口的区域
SetWindowRgn((HRGN)rgn,TRUE);
}
void CDemoDlg::OnButton18()
{
CRect rect;
GetClientRect(rect);
CPoint point[6];
point[0].x = 0;
point[0].y = rect.Height() / 2;
point[1].x = rect.Width() / 3;
point[1].y = 0;
point[2].x = 2 * rect.Width() / 3;
point[2].y = 0;
point[3].x = rect.Width();
point[3].y = rect.Height() / 2;
point[4].x = 2 * rect.Width() / 3;
point[4].y = rect.Height();
point[5].x = rect.Width() / 3;
point[5].y = rect.Height();
//创建多边形区域
CRgn rgn;
rgn.CreatePolygonRgn(point,6,ALTERNATE);
//设置窗口的区域
SetWindowRgn((HRGN)rgn,TRUE);
}
void CDemoDlg::OnButton19()
{
CRect rect;
GetClientRect(rect);
//创建圆矩形区域
CRgn rgn;
rgn.CreateRoundRectRgn(0,0,rect.Width(),rect.Height(),rect.Width() / 2,rect.Height() / 2);
//设置窗口的区域
SetWindowRgn((HRGN)rgn,TRUE);
}
13
设置窗口的透明区域
要设置窗口
的透明区域
,首先调用CRgn::CreateRectRgn
创建一个区域
,然后调用CRgn::CombineRgn
函数,去掉需要透明的区域
,最后调用CWnd::SetWindowRgn
函数按窗口区域
设置它.
void CDemoDlg::OnButton20()
{
CRect rect1;
GetWindowRect(rect1);
CRect rect2;
GetClientRect(rect2);
ClientToScreen(rect2);
CRgn rgn1;
rgn1.CreateRectRgn(rect1.left,rect1.top,rect1.right,rect1.bottom);
CRgn rgn2;
rgn2.CreateRectRgn(rect2.left,rect2.top,rect2.right,rect2.bottom);
CRgn rgn;
rgn.CreateRectRgn(0,0,1,1);
rgn.CombineRgn(&rgn1,&rgn2,RGN_DIFF);
//设置窗口区域
SetWindowRgn((HRGN)rgn,TRUE);
}
14
透明窗口
要实现透明窗口
,首先调用CWnd::ModifyStyleEx
函数,添加窗口的WS_EX_LAYERED(0x00080000)
扩展风格,然后调用SDK
的SetLayeredWindowAttributes
函数设置窗口的透明和透明色
.
void CDemoDlg::OnButton21()
{
//添加`WS_EX_LAYERED(0x80000)`扩展风格
ModifyStyleEx(0,0x80000);
//加载`User32.DLL`动态链接库
HMODULE hModule = LoadLibrary("User32.DLL");
if (hModule != NULL)
{
typedef BOOL (WINAPI *FUNC)(HWND,COLORREF,BYTE,DWORD);
//取得`SetLayeredWindowAttributes`函数指针
FUNC func = (FUNC)GetProcAddress(hModule,"SetLayeredWindowAttributes");
if (func != NULL)
{
func(GetSafeHwnd(),0,128,2);
}
FreeLibrary(hModule);
}
}
15
窗口闪烁
可调用CWnd::FlashWindow
函数闪烁窗口.
void CDemoDlg::OnButton22()
{
//设置计时器
SetTimer(1,1000,NULL);
}
void CDemoDlg::OnButton23()
{
//关闭计时器
KillTimer(1);
//窗口返回原状态
FlashWindow(FALSE);
}
void CDemoDlg::OnTimer(UINT nIDEvent)
{
if (nIDEvent == 1)
{
//窗口从一个状态闪烁到另一个状态
FlashWindow(TRUE);
}
CDialog::OnTimer(nIDEvent);
}
16
图片窗口
要实现图片窗口
,首先调用CRgn::CreateRectRgn
和CRgn::CombineRgn
函数创建并合并多个区域
,然后调用CWnd::SetWindowRgn
函数按窗口区域
设置它.
VC
对话框如何添加WM_ERASEBKGND
消息(OnEraseBkgnd
函数):
void CDemoDlg::OnButton24()
{
CRect rect;
GetWindowRect(&rect);
//加载位图
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP);
//将位图选入设备环境
CDC dc;
CDC *pDC = GetDC();
dc.CreateCompatibleDC(pDC);
dc.SelectObject(&bmp);
//将位图中黑色区域变成透明区域
CRgn rgn1;
rgn1.CreateRectRgn(0,0,rect.Width(),rect.Height());
for (int x = 0;x < rect.Width();x++)
{
for (int y = 0;y < rect.Height();y++)
{
COLORREF cr = dc.GetPixel(x,y);
if (cr == RGB(0,0,0))
{
CRgn rgn2;
rgn2.CreateRectRgn(x,y,x+1,y+1);
rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR);
}
}
}
//设置窗口区域
SetWindowRgn((HRGN)rgn1,TRUE);
ReleaseDC(pDC);
}
//添加`WM_ERASEBKGND`消息处理函数
BOOL CDemoDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetWindowRect(&rect);
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP);
CDC dc;
dc.CreateCompatibleDC(pDC);
dc.SelectObject(&bmp);
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
return TRUE;
}
17
动画窗口
可调用SDK
的动画窗口
函数,实现动画窗口
.
BOOL CDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//...居中窗口
CenterWindow();
//显示动画窗口
AnimateWindow(GetSafeHwnd(), 3000, AW_BLEND);
return TRUE;
}
18
桌面窗口
可调用CWnd::GetDesktopWindow
函数,取得桌面窗口
.
void CDemoDlg::OnButton25()
{
//取得桌面窗口
CWnd* pWnd = CWnd::GetDesktopWindow();
//取得窗口大小
CRect rect;
pWnd->GetClientRect(rect);
CString strText = _T("");
strText.Format(_T("桌面窗口大小:%dX%d"),rect.Width(),rect.Height());
AfxMessageBox(strText);
}
19
最小化桌面所有窗口
窗口
中可利用快捷键Win+M
最小化所有窗口.因此,可通过向任务栏窗口
发送ID
为0x1F5(Win+M
)的WM_HOTKEY
消息,来最小化桌面所有窗口
.
首先调用CWnd::FindWindow
函数取得窗口
,然后调用CWnd::SendMessage
函数向窗口发送消息
.
void CDemoDlg::OnButton26()
{
//取得任务栏窗口
CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
//发送`ID`为`0x1F5(Win+M)`的`WM_HOTKEY`消息
pWnd->SendMessage(WM_HOTKEY,0x1F5);
}
20
取任务栏窗口
可调用CWnd::FindWinow
函数,取得任务栏窗口
.
void CDemoDlg::OnButton27()
{
//取得任务栏窗口
CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
//取得窗口大小
CRect rect;
pWnd->GetClientRect(rect);
CString strText = _T("");
strText.Format(_T("任务栏窗口大小:%dX%d"),rect.Width(),rect.Height());
AfxMessageBox(strText);
}
21
显示或隐藏任务栏
显示或隐藏任务栏
;首先调用CWnd::FindWindow
函数取得窗口
,然后调用CWnd::ShowWindow
函数隐藏或显示窗口
.
void CDemoDlg::OnButton28()
{
//取得任务栏窗口
CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
//隐藏窗口
if (pWnd->IsWindowVisible())
{
pWnd->ShowWindow(SW_HIDE);
}
}
void CDemoDlg::OnButton29()
{
//取得任务栏窗口
CWnd* pWnd = CWnd::FindWindow(_T("Shell_TrayWnd"),NULL);
//显示窗口
if (!pWnd->IsWindowVisible())
{
pWnd->ShowWindow(SW_SHOW);
}
}
22
枚举桌面所有顶层窗口
BOOL CDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//...初化列表框控件
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST);
pList->ModifyStyle(LVS_ICON | LVS_SMALLICON | LVS_LIST,LVS_REPORT);
pList->SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
pList->InsertColumn(0,_T("窗口类名"),LVCFMT_LEFT,115);
pList->InsertColumn(1,_T("窗口标题"),LVCFMT_LEFT,150);
return TRUE;
}
枚举桌面
所有顶层窗口
有两个方法
:
a,调用CWnd::GetDesktopWindow
和CWnd::GetWindow
函数:首先调用CWnd::GetDesktopWindow
函数,取得桌面窗口
,然后调用CWnd::GetWindow
函数,枚举所有子窗口
.
void CDemoDlg::OnButton30()
{
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST);
pList->DeleteAllItems();
pList->SetRedraw(FALSE);
//取得桌面窗口
CWnd* pDesktopWnd = CWnd::GetDesktopWindow();
//取得第一个子窗口
CWnd* pWnd = pDesktopWnd->GetWindow(GW_CHILD);
while(pWnd != NULL)
{
int nItem = pList->GetItemCount();
//取得窗口类名
CString strClassName = _T("");
::GetClassName(pWnd->GetSafeHwnd(),strClassName.GetBuffer(256),256);
strClassName.ReleaseBuffer();
pList->InsertItem(nItem,strClassName);
//取得窗口标题
CString strWindowText = _T("");
::GetWindowText(pWnd->GetSafeHwnd(),strWindowText.GetBuffer(256),256);
strWindowText.ReleaseBuffer();
pList->SetItemText(nItem,1,strWindowText);
//继续取得下个子窗口
pWnd = pWnd->GetWindow(GW_HWNDNEXT);
}
pList->SetRedraw(TRUE);
}
b,调用SDK
的EnumWindows
函数.
//添加全局函数
BOOL CALLBACK EnumWndPorc(HWND hWnd,LPARAM lParam)
{
if (hWnd == NULL)
{
return FALSE;
}
CListCtrl* pList = (CListCtrl*)lParam;
int nItem = pList->GetItemCount();
//取得窗口类名
CString strClassName = _T("");
::GetClassName(hWnd,strClassName.GetBuffer(256),256);
strClassName.ReleaseBuffer();
pList->InsertItem(nItem,strClassName);
//取得窗口标题
CString strWindowText = _T("");
::GetWindowText(hWnd,strWindowText.GetBuffer(256),256);
strWindowText.ReleaseBuffer();
pList->SetItemText(nItem,1,strWindowText);
return TRUE;
}
void CDemoDlg::OnButton31()
{
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST);
pList->DeleteAllItems();
pList->SetRedraw(FALSE);
//枚举窗口
::EnumWindows(EnumWndPorc,(LPARAM)pList);
pList->SetRedraw(TRUE);
}