MFC第十五天 HWND与CWnd对象之间的转换、CWnd类简介(补充)、员工管理系统登录界面眼睛捕获(补充)

文章目录

  • HWND与CWnd对象之间的转换
  • CWnd类简介(补充)
    • cwnd系统函数
    • Coordinate Mapping Functions 坐标系转换
    • 窗口树 Window tree access
    • 计时器管理
    • Window Access Functions 窗口访问功能
    • Window Text Functions 窗口文本函数
    • Window State Functions
    • CMenu Functions - non-Child windows only 仅限非子窗口
    • Window Size and Position Functions
    • Icon Functions AND Alert Functions
    • 窗口捕获和聚焦:
    • CWnd类中相应方法实例
  • 在员工管理系统中登录界面的眼睛 使用setcapture来进行捕捉如下
    • CLoginDlg.h
    • CLoginDlg.cpp
    • CEyeCtrl.h
    • CEyeCtrl.cpp

HWND与CWnd对象之间的转换

a)如果有CWnd对象如何获取这个对象内部的句柄?
pWnd ->m_hWnd
pWnd ->GetSafeHwnd(); //获取当前窗口的句柄
CWnd wnd;
HWND h = wnd;
b)如果有句柄HWND如何转为CWnd?
static CWnd* CWnd::FromHandle(HWND hWnd); //根据给定的句柄(handle)获取相应的CWnd对象
c)注意:GetDlgItem内部都是靠FromHandle实现的。
d)注意:FromHandle内部是有Map禁止一个句柄被多个对象包含。
就如同一个端口只能被一个进程占用,一个句柄只能有一个对象包含。
e)注意:FromHandle的返回值只限于本函数使用,不可以保存在成员变量长期使用。
原因是不定期清理Map,参见:CWnd::DeleteTempMap

FromHandle示例:

 // 假设有一个对话框类 CMyDialog,它继承自 CDialog
HWND hDlg = m_MyDialog.GetSafeHwnd();// 获取对话框句柄
CWnd* pWnd = CWnd::FromHandle(hDlg);// 通过对话框句柄获取 CWnd 对象
if (pWnd != NULL)// 验证 pWnd 是否为有效指针
{    pWnd->SetWindowText(_T("My Dialog"));   // 设置对话框的标题
    
    CRect rect;
    pWnd->GetClientRect(&rect);  // 获取对话框的客户区矩形
    CDC* pDC = pWnd->GetDC();    // 绘制一个红色矩形框
    pDC->SelectStockObject(NULL_BSH);
    pDC->SelectStockObject(DC_PEN);
    pDC->SetDCPenColor(RGB(255, 0, 0));
    pDC->Rectangle(rect);
    pWnd->ReleaseDC(pDC);
}

通过对话框对象的GetSafeHwnd()函数获取对话框句柄。然后使用FromHandle()函数将句柄转换为CWnd指针。接下来通过该指针对对话框进行各种操作,例如设置标题、获取客户区矩形并绘制矩形框等。需要注意的是,使用FromHandle()函数从句柄获取CWnd对象后,需要进行有效性检查,以确保返回的指针不为空。

CWnd类简介(补充)

cwnd系统函数

class CWnd : public CCmdTarget
{
public:
	HWND m_hWnd;            // must be first data member

	static CWnd* PASCAL FromHandle(HWND hWnd);
	static CWnd* PASCAL FromHandlePermanent(HWND hWnd);
	static void PASCAL DeleteTempMap();
	//用于删除临时映射。当您不再需要使用文件的临时映射时,通常会调用此函数。

	BOOL Attach(HWND hWndNew);
	HWND Detach();
	
	BOOL SubclassWindow(HWND hWnd);
	BOOL SubclassDlgItem(UINT nID, CWnd* pParent);
	HWND UnsubclassWindow();

	operator HWND() const
	{ return this == NULL ? NULL : m_hWnd; }
	BOOL operator==(const CWnd& wnd) const
	{return wnd.GetSafeHwnd() == this ->GetSafeHwnd();}
//这样写程序不安全 { return wnd.m_hWnd == m_hWnd; }
_AFXWIN_INLINE BOOL CWnd::operator!=(const CWnd& wnd) const
	{return wnd.GetSafeHwnd() != GetSafeHwnd();}

HWND CWnd::GetSafeHwnd() const
	{ return this == NULL ? NULL : m_hWnd; }

	static AFX_DATA const CWnd wndTop; // SetWindowPos's pWndInsertAfter
	static AFX_DATA const CWnd wndBottom; // SetWindowPos's pWndInsertAfter
	static AFX_DATA const CWnd wndTopMost; // SetWindowPos pWndInsertAfter
	static AFX_DATA const CWnd wndNoTopMost; // SetWindowPos pWndInsertAfter

	BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y,int cx, int cy, UINT nFlags);
	void MoveWindow(int x, int y, int nWidth, int nHeight,BOOL bRepaint = TRUE);
	void MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE);

	// for child windows, views, panes etc 创建子窗口,后来在所有派生类中都重写了Create函数。
	virtual BOOL Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,
		const RECT& rect,CWnd* pParentWnd, UINT nID,CCreateContext* pContext = NULL);

	// advanced creation (allows access to extended styles) :创建框架的
	virtual BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
		LPCTSTR lpszWindowName, DWORD dwStyle,int x, int y, int nWidth, int nHeight,
		HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL);
	//增强风格的子窗口
	virtual BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,LPCTSTR lpszWindowName, 
	DWORD dwStyle,const RECT& rect,CWnd* pParentWnd, UINT nID,LPVOID lpParam = NULL);
	virtual BOOL DestroyWindow();

Coordinate Mapping Functions 坐标系转换

	void GetWindowRect(LPRECT lpRect) const;
	void GetClientRect(LPRECT lpRect) const;
	void ClientToScreen(LPPOINT lpPoint) const;
	void ClientToScreen(LPRECT lpRect) const;
	void ScreenToClient(LPPOINT lpPoint) const;
	void ScreenToClient(LPRECT lpRect) const;

窗口树 Window tree access

	int GetDlgCtrlID() const; 获取一个窗口ID
	int SetDlgCtrlID(int nID); 修改窗口ID
		// get and set window ID, for child windows only
	CWnd* GetDlgItem(int nID) const; 获取子窗口句柄(内部用FromHandle创建一个外壳类对象)
		// get immediate child with given ID
	void GetDlgItem(int nID, HWND* phWnd) const; 直接返回子控件的句柄
		// as above, but returns HWND
	CWnd* GetDescendantWindow(int nID, BOOL bOnlyPerm = FALSE) const;  
		在子孙孙内获取ID对应的句柄(内部调用FromHandle创建外壳类对象)
		// like GetDlgItem but recursive

计时器管理

	UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse,
	void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD));
	BOOL KillTimer(UINT_PTR nIDEvent);

Window Access Functions 窗口访问功能

	 //为什么主窗口用一个点去探测,不用面向对象?
	static CWnd* PASCAL WindowFromPoint(POINT point); 
	CWnd* ChildWindowFromPoint(POINT point) const;//为什么子窗口要面向对象
	CWnd* ChildWindowFromPoint(POINT point, UINT nFlags) const;
	CWnd* GetTopWindow() const;
	BOOL IsChild(const CWnd* pWnd) const; 判断一个窗口是不是它的子窗口之一

	CWnd* GetParent() const;获取父窗口
	CWnd* SetParent(CWnd* pWndNewParent); //设置父窗口
	CWnd* GetNextWindow(UINT nFlag = GW_HWNDNEXT) const;
	CWnd* GetWindow(UINT nCmd) const;
 	//可以获取该窗口的父亲GW_OWNER   ,儿子GW_CHILD    和兄弟(GW_HWNDNEXT)

Window Text Functions 窗口文本函数

	void SetWindowText(LPCTSTR lpszString);
	int GetWindowText(_Out_writes_to_(nMaxCount, return + 1) LPTSTR lpszStringBuf, _In_ int nMaxCount) const;
	void GetWindowText(CString& rString) const;
	int GetWindowTextLength() const;
	void SetFont(CFont* pFont, BOOL bRedraw = TRUE);
	CFont* GetFont() const;

Window State Functions

	BOOL IsWindowEnabled() const;//禁用和激活
	BOOL EnableWindow(BOOL bEnable = TRUE);

	LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) const;
	BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0);
	void SendMessageToDescendants(UINT message, WPARAM wParam = 0,
		LPARAM lParam = 0, BOOL bDeep = TRUE, BOOL bOnlyPerm = FALSE);

CMenu Functions - non-Child windows only 仅限非子窗口

	virtual CMenu* GetMenu() const; //设置和获取菜单
	virtual BOOL SetMenu(CMenu* pMenu); 
	void DrawMenuBar();
	CMenu* GetSystemMenu(BOOL bRevert) const; //系统菜单
	BOOL HiliteMenuItem(CMenu* pMenu, UINT nIDHiliteItem, UINT nHilite);

Window Size and Position Functions

	BOOL IsIconic() const; 判断窗口最小化 相当于:GetStyle()&WS_MINIMIZE
	BOOL IsZoomed() const; 判断窗口最大化 相当于:GetStyle()&WS_MAXIMIZE

	int SetWindowRgn(HRGN hRgn, BOOL bRedraw); 不规则窗口(椭圆窗口,圆角窗口,五边形窗口)
	int GetWindowRgn(HRGN hRgn) const;

	void BringWindowToTop();
	// the active window applies only to top-level (frame windows)
	static CWnd* PASCAL GetActiveWindow(); 参见AfxGetMainWnd()
	CWnd* SetActiveWindow(); //将指定的窗口置于所有其他窗口的前面,并将焦点设置在该窗口上。

	// the foreground window applies only to top-level windows (frame windows)
	BOOL SetForegroundWindow(); //将窗口设置为前台窗口
	static CWnd* PASCAL GetForegroundWindow();

Icon Functions AND Alert Functions

// Icon Functions
	HICON SetIcon(HICON hIcon, BOOL bBigIcon);
	HICON GetIcon(_In_ BOOL bBigIcon) const;

// Alert Functions
	BOOL FlashWindow(BOOL bInvert);

窗口捕获和聚焦:

	// capture and focus apply to all windows
	static CWnd* PASCAL GetCapture();
	CWnd* SetCapture(); //ReleaseCaptue是API不封装为什么呢?你想想SetCursor也是API不封装?
	//必须在合适的时机调用ReleaseCapture函数来释放捕获
	//SetCapture函数只能捕获鼠标输入,无法捕获键盘输入
	//如果需要捕获键盘输入,可以使用SetKeyboardState函数配合GetAsyncKeyState函数实现。

	static CWnd* PASCAL GetFocus(); 
	CWnd* SetFocus();

	static CWnd* PASCAL GetDesktopWindow(); //调用即可返回当前桌面的窗口句柄

CWnd类中相应方法实例

MFC第十五天 HWND与CWnd对象之间的转换、CWnd类简介(补充)、员工管理系统登录界面眼睛捕获(补充)_第1张图片

void CMainDlg::OnBnClickedSendmessage()
{
	auto p = FindWindow(_T("Notepad"), NULL);
	if (p)
		p->SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}


void CMainDlg::OnBnClickedPostmessage()
{
	auto p = FindWindow(_T("Notepad"), NULL);
	if (p)
		p->SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
}


void CMainDlg::OnBnClickedButton3()
{
	auto p = GetDlgItem(IDOK);
	auto q = p->GetOwner();
	ASSERT(q == this);
	//auto b = this->IsChild(p);
}

void Search(CWnd* p)
{
	if (!p)
		return;
	auto q = p->GetWindow(GW_CHILD);
	TCHAR s[256];
	while (q)
	{
		GetClassName(q->GetSafeHwnd(), s, _countof(s));
		TRACE(_T("q=%s\n"), s);
		Search(q);
		q = q->GetWindow(GW_HWNDNEXT);
	}
}
 
void CMainDlg::OnBnClickedButton1()
{
	auto p = FindWindow(_T("CabinetWClass"), NULL);
	Search(p);
}


void CMainDlg::OnBnClickedButton2()
{
	auto p = FindWindow(_T("Notepad"), NULL);
	if (p)
		p->BringWindowToTop();
}

/*
BringWindowToTop函数只负责将窗口置于最前端,而不会激活窗口;
而SetForegroundWindow函数不仅将窗口置于最前端,还会将其激活成为焦点窗口
*/

void CMainDlg::OnBnClickedButton4()
{
	auto p = FindWindow(_T("Notepad"), NULL);
	if (p)
		p->SetForegroundWindow();
}


void CMainDlg::OnBnClickedButton5()
{
	auto p = FindWindow(_T("Notepad"), NULL);
	if (p)
		p->FlashWindow(TRUE);
}


void CMainDlg::OnBnClickedButton6()
{
	auto p = GetDesktopWindow();
	p = p->GetWindow(GW_CHILD); //主窗口遍历和子窗口搜索
	TCHAR s[256];
	while (p)
	{
		//GetClassName(p->GetSafeHwnd(), s, _countof(s));
		p->GetWindowText(s, _countof(s));
		TRACE(_T("主窗口:%s\n"), s);
		p = p->GetWindow(GW_HWNDNEXT);
	}
}

在员工管理系统中登录界面的眼睛 使用setcapture来进行捕捉如下

MFC第十五天 HWND与CWnd对象之间的转换、CWnd类简介(补充)、员工管理系统登录界面眼睛捕获(补充)_第2张图片

消息分类:系统消息和用户消息:
a)类向导中第一页和第二页子窗口(反射型)消息和主窗口基础消息,全部都是系统消息。
b)系统消息的范围是:0-1024(WM_USER),用户消息(也叫自定义消息)的WM_USER到32767之间。

消息发送的用途:
a)往往是一个多线程程序的底层工作线程,向主线程的界面发送通知(包含数据)
b)子窗口向父窗口发送消息(可能携带数据)
c)一个进程向另外一个进程发送消息(可能携带数据)
d)对windows控件发送指令,SendMessage(LVM_INSERTCOLUMN,&col);
注意:自从有了消息发送的方法之后,子窗口可以不再使用指针来调用符窗口了!!
参见CEyeCtrl:甚至都不知道父窗口是哪个类!!

1.定义用户消息 消息法都会定义这个宏 或者之前用到的指针法
消息法,它连它老爸是谁都不知道 便于移植

enum {UM_LBDOWN = WM_USER+999,UM_LBUP};  

2.在CLoginDlgl类使用–>类向导–>添加自定义消息
MFC第十五天 HWND与CWnd对象之间的转换、CWnd类简介(补充)、员工管理系统登录界面眼睛捕获(补充)_第3张图片

MFC第十五天 HWND与CWnd对象之间的转换、CWnd类简介(补充)、员工管理系统登录界面眼睛捕获(补充)_第4张图片

CLoginDlg.h

protected:
	afx_msg LRESULT OnUmLbdown(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnUmLbup(WPARAM wParam, LPARAM lParam);

CLoginDlg.cpp

afx_msg LRESULT CLoginDlg::OnUmLbdown(WPARAM wParam, LPARAM lParam)
{
	auto pEdit = reinterpret_cast<CEdit*>(GetDlgItem(IDC_PASS));
	pEdit->SetPasswordChar(0);
	pEdit->RedrawWindow();
	return 0;
}
afx_msg LRESULT CLoginDlg::OnUmLbup(WPARAM wParam, LPARAM lParam)
{
	auto pEdit = reinterpret_cast<CEdit*>(GetDlgItem(IDC_PASS));
	pEdit->SetPasswordChar(_T('●'));
	pEdit->RedrawWindow();
	return 0;
}

CEyeCtrl.h

#pragma once
class CLoginDlg;  //提前声明,假包含
class CEyeCtrl : public CWnd
{
	DECLARE_DYNAMIC(CEyeCtrl)	 
public:
	CEyeCtrl();
	virtual ~CEyeCtrl();
protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};

CEyeCtrl.cpp

// CEyeCtrl 消息处理程序
void CEyeCtrl::OnLButtonDown(UINT nFlags, CPoint point){
	auto p = GetParent();
	if (p)
		p->SendMessage(UM_LBDOWN);		
	SetCapture();  //窗口捕捉 锁定光标	
	CWnd::OnLButtonDown(nFlags, point);
}
void CEyeCtrl::OnLButtonUp(UINT nFlags, CPoint point){
	auto p = GetParent();
	if (p)
		p->SendMessage(UM_LBUP);
	ReleaseCapture();  //当离开捕获就会弹起
	CWnd::OnLButtonUp(nFlags, point);
}

你可能感兴趣的:(MFC开发,mfc,c++)