1.窗口、控件的指針和句柄的相互轉化
1)指針轉化為句柄在MFC應用程序中首先要獲得窗口的指針,然后將其轉化為句柄 CWnd* pWnd; HANDLE hWnd = pWnd->GetSafeHwnd();
2)句柄轉化為指針在MFC應用程序中首先獲得對話框控件的句柄,然后獲得其指針HANDLE hWnd;GetDlgItem(IDC_xxx,&hWnd);CWnd * pWnd = FromHandle(hWnd);
獲得程序窗口指針的辦法:
a.獲得主框架窗口指針(任何時候都可以用,只要是MFC程序中):
CWnd* pWnd = AfxGetMainWnd();
b.獲得對話框中控件指針:
CWnd* pWnd = GetDlgItem(IDC_xxx);
c.獲得對話框中某控件的句柄:
HANDLE GetDlgItem(m_hDLG,m_nID_DlgItem);
d.獲得GDI對象的句柄:
HANDLE m_hGDIObj = m_pGDIObj->GetSafeHanle();
2. 如何獲取應用程序的實例句柄?
AfxGetInstanceHandle()應用程序的 實例句柄保存在CWinAppIm_hInstance 中,可以這么調用 AfxGetInstancdHandle獲得句柄;
Example: HANDLE hInstance=AfxGetInstanceHandle();
3. 如何通過代碼獲得應用程序主窗口的指針?
AfxGetMainWnd GetSafeHwnd() AfxGetAppName() AfxGetThread
主窗口的 指針保存在CWinThread::m_pMainWnd中,調用 AfxGetMainWnd實現。
【例】 AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最大化.
【例】此例的主窗口是對話框,下面的代碼是在另外一個CFileTreeCtrl 類(子窗)中相關函數實現在主對話框(主窗)中的幾個 靜態文本框(子窗)中顯示路徑:
CWnd* m_pCWnd= AfxGetMainWnd(); //得到主窗口指針,通過主窗指針訪問其他子窗資源
//方法一
m_pCWnd->SetDlgItemText(IDC_STATIC_path,"CWnd* "+m_sCurPath); //在主窗中的子窗(ID:IDC_STATIC_path)中顯示字符串
m_pCWnd->SetDlgItemText(IDC_STATIC_who,"路徑顯示由FileTreeCtrl類完成:");
//方法二
m_pCWnd->SendMessage(STN_CLICKED); //向主窗口發送一個消息,顯示任務由主窗完成。
//在主窗的.cpp中有:ON_MESSAGE(STN_CLICKED, OnSTATICpath3)相關描述
//有的函數必須通過窗口的 句柄 來訪問,我們可以使用下面的方法三
//CWnd::GetSafeHwnd
//Returns the window handle for a window
//HWND GetSafeHwnd( ) const;
HWND m_hWnd_tree =GetSafeHwnd();//【注】此處得到的只是當前窗口(FileTree類)的句柄
HWND m_hWnd = m_pCWnd->GetSafeHwnd();// 這里才是主窗口的句柄(由主窗指針得到主窗的句柄)
//BOOL SetWindowText( HWND hWnd, LPCTSTR lpString )
::SetWindowText(m_hWnd,"ok2222");//修改主窗口標題
::SetDlgItemText(m_hWnd,IDC_STATIC_path2,"HWND: "+m_sCurPath);
【另】AfxGetThread
CWinThread* AfxGetThread( );
Return Value:Pointer to the currently executing thread.
4.如何在程序中獲得其他程序的圖標?
AfxGetInstanceHandle()
HINSTANCE AfxGetInstanceHandle( );
Return Value
An HINSTANCE to the current instance of the application.
If called from within a DLL linked with the USRDLL version of MFC, an HINSTANCE to the DLL is returned.
Remarks
This function allows you to retrieve the instance handle of the current application.
AfxGetInstanceHandle always returns the HINSTANCE of your executable file (.EXE) unless it is called from within a DLL linked with the USRDLL version of MFC.
In this case, it returns an HINSTANCE to the DLL.
兩種方法:
(1) SDK函數 SHGetFileInfo 或使用 ExtractIcon獲得圖標資源的 handle(句柄),
(2) SDK函數 SHGetFileInfo獲得有關文件的 很多信息,如大小圖標,屬性,類型等.
Example(1): 在程序窗口左上角顯示 NotePad圖標.
void CSampleView: OnDraw(CDC * pDC)
{
if( :: SHGetFileInfo(_T("c:\\pwin95\\notepad.exe"),0,&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
{
pDC ->DrawIcon(10,10,stFileInfo.hIcon);
}
}
Example(2):同樣功能,Use ExtractIcon Function
void CSampleView:: OnDraw(CDC *pDC)
{
HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);
if (hIcon &&hIcon!=(HICON)-1)
pDC->DrawIcon(10,10,hIcon);
}
【說明】關於如何得到系統文件的正確路徑,象win.ini system32.ini等的路徑,各種系統中具體的路徑是不一樣的。如:獲得notepad.exe的路徑正規上來說用;
GetWindowsDirectory 函數得到;如果是調用 win95下的畫筆,應該用訪問注冊表的方法獲得其路徑;要作成一個比較考究的程序,考慮應該全面點.
HINSTANCE AfxGetResourceHandle( );
Return Value:An HINSTANCE handle where the default resources of the application are loaded。
5. 有關取得桌面句柄 GetDesktopWindow()
MSDN中的例子:
// 靜態函數CWnd:: GetDesktopWindow 返回桌面窗口的指針。下例說明了MFC
void CFrameWnd::BeginModalState ()
{
//first count all windows that need to be disabled
UINT nCount=0;
HWND hWnd=:: GetWindow (:: GetDesktopWindow (), GW_CHILD);
while (hWnd!=NULL)
{
if (:: IsWindowEnabled (hwnd) &&
CWnd::FromHandlePermanent (hWnd)!=NULL &&
AfxIsDescendant (pParent->m_hWnd, hWnd) &&
:: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0) == 0)
{
++nCount;
}
hWnd=:: GetWindow (hWnd, GW_HWNDNEXT);
}
}
//用戶的問題:下面程序取的不是同一程序的句柄,但是GetModuleFileName返回的結果一樣請問為什么
HWND ChWnd;//子窗口句柄
HWND hwDesktop=::GetDesktopWindow();//取得桌面句柄
ChWnd=::GetWindow(hwDesktop,GW_CHILD);//取得桌面子句柄
CString csTitle,csClass,csTm,mLookstring;
char szBuffer255];
while(ChWnd!=NULL)//循環取子句柄的同級句柄
{
if(::IsWindowVisible(ChWnd))//判斷是否為可顯示窗口
{
::GetWindowText(ChWnd,csTitle.GetBuffer(255),254);
::GetClassName(ChWnd,csClass.GetBuffer(255),254);
csTitle.ReleaseBuffer();//標題
csClass.ReleaseBuffer();//類名
csTm.Format("%08X:",ChWnd);
if(csTitle=="")
{
mLookstring=csTm+csClass;
}
else
{
mLookstring=csTm+csTitle;
}
//這里的窗口句柄不是同一個程序吧?(問題所在!)可是為什莫結果一樣
HINSTANCE hInstance = (HINSTANCE)::GetWindowLong(ChWnd,DWL_USER);
::GetModuleFileName(hInstance, szBuffer, sizeof(szBuffer));
MessageBox(szBuffer,mLookstring);
}
ChWnd=::GetWindow(ChWnd,GW_HWNDNEXT);
}
回答:
問題在於Win32下GetWindowLong(ChWnd,DWL_USER)總是返回當前程序運行的hInstance,所以你得到文件名總是一個。所以你要用枚舉所有"進程的程序名"來獲得程序名。
再談句柄與指針的區別
許多開始學習VC的朋友,最多聽說的兩個詞莫過於指針和句柄了。
但是,確經常搞不清他們之間的區別。
首先,句柄是一個窗口的標志,也就是所有從CWND類繼承下來的,多有句柄這個成員。他能做的,也就是唯一代表一個桌面上的窗口罷了。而指針是一個地址,如果它指向了
一個內存中的對象,那么就可以對它進行任意操作了,當然,並不局限於自己的應用程序,你如果能夠獲得別的應用程序的某個對象的指針,也可以進行操作。
然而,如果要獲得指針,首先,必須找到那個窗口的句柄,然后用函數FromHandle就可以得到他的指針了。
問題1:
如何在自定義的消息中發送一個字符串?例如:
SendMessage(MyWnd,WM_USERDEFINED, 0,0)
如何將字符串Buffer寫入wParam或lParam?
你可以把字符串的地址傳遞過去,因為地址正好是32位。如:
char s256];
SendMessage(MyWnd,WM_USERDEFINED, (WPARAM) s,0)
接收方只需要將wParam賦給一個char*就可以了。但此方法只能使用於在一個進程內部傳遞數據。
問題2:
1).在VC應用程序框架中,如何加入自己做的類,如何定義這個類的對象,我想在鼠標點擊某個菜單項的時候才生成這個對象,做得到嗎?(這個類的構造函數是帶參數的)。
2).消息發送函數:
PostMessage(HWND handle,WM_MYMESSAGE, WPARAM wParam,LPARAM lParam) 中:
第一個參數如何獲得?
如果我的消息是在自己的應用程序中生成的,想發給應用程序的窗口讓它顯示某些數據(用TextOut函數),能做到嗎?
(也可以說是這樣的問題:用Appwizard生成應用程序框架,在生成的類(如CView)中如何得到窗口的句柄,並放在PostMessage函數中。)
3).wParam,lParam,在消息響應函數中如何用?vc是怎樣保證這兩個數傳到函數中的?問題比較多,謝謝!
回答:
a.這個問題是肯定的。你可以使用ClassWizard定義類,也可以手工輸入。如果類定義已經在某個文件中,只要使用Project|Add files將文件加入工程就可以了。
要想定義類的對象,只要在你的菜單項的相應事件中就可以了。如:
{
MyClass myObject("Hello");
myObject.MyMethod();
}
b.在你自己的程序中傳遞消息當然沒有任何問題,只要你知道要調用的窗口類是從CWnd繼承來的,你就可以使用GetSafeHwnd函數獲得窗口句柄。
不過一般在自己的同一個程序中有時不願意使用自定義消息,因為太麻煩。你完全可以給要調用的類添加一個成員函數,只要想顯示數據,直接調用這個成員函數不就可以了?
何必使用PostMessage呢?
一般只有在程序間調用,才願意使用自定義消息。這時,你通常可以使用FindWindow獲得窗口句柄(QA000251 "如何利用FindWindow()函數查找程序")。
c.對於MFC已經定義了消息處理函數的消息,MFC會自動把wParam和lParam映射為更容易使用的方式。如OnMouseMove( UINT nFlags, CPoint point )。
對於MFC不能自動處理的函數,如你使用ON_MESSAGE定義消息函數,則MFC會把wParam和lParam原原本本的傳遞給你的函數,不做任何處理。
一個未公開的Win32 API函數:GetTaskmanWindow ()
下例中還用到: GetProcAddress GetParent(hWnd)
HMODULE hUser32 = GetModuleHandle("user32");
download
// getaskmanwnd.cpp (Windows NT/2000)
//
// 利用一個未公開的Win32 API函數:GetTaskmanWindow,
// 對Windows的任務欄進行操作(顯示/隱藏)。這個函數返回擁有任務欄按鈕的窗口句柄。
//
// This example will show you how you can obtain a handle to the
// Windows Taskbar window.
//
// (c)1999 Ashot Oganesyan K, SmartLine, Inc
// mailto:ashot@aha.ru, http://www.protect-me.com, http://www.codepile.com
#include <windows.h>
#include <stdio.h>
// User32!GetTaskmanWindow (NT specific!)
//
// This function returns a handle to the window that ownes the taskbar buttons
//
// HWND GetTaskmanWindow()
//
typedef HWND (WINAPI *PROCGETTASKMANWND)(void);
PROCGETTASKMANWND GetTaskmanWindow;
void main(int argc, char* argv])
{
if (argc<2)
{
printf("Usage:\n\ngetaskmanwnd.exe S|H\n");
return;
}
HMODULE hUser32 = GetModuleHandle("user32");
if (!hUser32)
return;
GetTaskmanWindow = (PROCGETTASKMANWND)GetProcAddress(hUser32,"GetTaskmanWindow");
if (!GetTaskmanWindow)
return;
HWND hWnd = GetTaskmanWindow();
if (!hWnd)
return;
if (*argv1]=="H" || *argv1]=="h")
ShowWindow(GetParent(hWnd),SW_HIDE);
else
ShowWindow(GetParent(hWnd),SW_SHOW);
}
6.總結:
在使用MFC時,窗口是經常使用的,所以大家在看完今天這篇,接下來勤加練習,成為C++大神指日可待。
改變自己,從現在做起-----------久館