重庆大学光电工程学院 贾旭滨 对 “句柄” “指针” 有下面的描述(AfxGetMainWnd GetSafeHwnd() AfxGetAppName() AfxGetThread)...
句????? 柄
出處: 方塘2003.9.22 整理,之所以前面引用了 賈旭濱 先生的這段描述,因?yàn)樗麑懙氖窃诰?#xff01;
=== 重慶大學(xué)光電工程學(xué)院 賈旭濱 對句柄有下面的描述:
? 句柄概念在WINDOWS編程中是一個(gè)很重要的概念,在許多地方都扮演著重要的角色。但由此而產(chǎn)生的句柄概念也大同小異,比如:<<Microsoft Windows 3 Developer's Workshop>>(Microsoft Press,by Richard Wilton)一書中句柄的概念是:在Windows環(huán)境中,句柄是用來標(biāo)識項(xiàng)目的,這些項(xiàng)目包括:
*.模塊(module)
*.任務(wù)(task)
*.實(shí)例(instance)
*.文件(file)
*.內(nèi)存塊(block of memory)
*.菜單(menu)
*.控制(control)
*.字體(font)
*.資源(resource),包括圖標(biāo)(icon),光標(biāo)(cursor),字符串(string)等
*.GDI對象(GDI object),包括位圖(bitmap),畫刷(brush),元文件(metafile),調(diào)色板(palette),畫筆(pen),區(qū)域(region),以及設(shè)備描述表(device context)。
? WINDOWS程序中并不是用物理地址來標(biāo)識一個(gè)內(nèi)存塊,文件,任務(wù)或動(dòng)態(tài)裝入模塊的,相反的,WINDOWS API給這些項(xiàng)目分配確定的句柄,并將句柄返回給應(yīng)用程序,然后通過句柄來進(jìn)行操作。
? 在<<WINDOWS編程短平快>>(南京大學(xué)出版社)一書中是這么說的:句柄是WONDOWS用來標(biāo)識被應(yīng)用程序所建立或使用的對象的唯一整數(shù),WINDOWS使用各種各樣的句柄標(biāo)識諸如應(yīng)用程序?qū)嵗?#xff0c;窗口,控制,位圖,GDI對象等等。WINDOWS句柄有點(diǎn)象C語言中的文件句柄。
? 從上面的2個(gè)定義中的我們可以看到,句柄是一個(gè)標(biāo)識符,是拿來標(biāo)識對象或者項(xiàng)目的,它就象我們的姓名一樣,每個(gè)人都會(huì)有一個(gè),不同的人的姓名不一樣,但是,也可能有一個(gè)名字和你一樣的人。從數(shù)據(jù)類型上來看它只是一個(gè)16位的無符號整數(shù)。應(yīng)用程序幾乎總是通過調(diào)用一個(gè)WINDOWS函數(shù)來獲得一個(gè)句柄,之后其他的WINDOWS函數(shù)就可以使用該句柄,以引用相應(yīng)的對象。在WINDOWS編程中會(huì)用到大量的句柄,比如:HINSTANCE(實(shí)例句柄),HBITMAP(位圖句柄),HDC(設(shè)備描述表句柄),HICON(圖標(biāo)句柄)等等,這當(dāng)中還有一個(gè)通用的句柄,就是HANDLE,比如下面的語句:
HINSTANCE hInstance;
可以改成:
HANDLE hInstance;
上面的2句語句都是對的。
一個(gè)WINDOWS應(yīng)用程序可以用不同的方法獲得一個(gè)特定項(xiàng)的句柄。許多API函數(shù),諸如CreateWindow,GlobalAlloc,OpenFile的返回值都是一個(gè)句柄值。另外,WINDOWS也能通過應(yīng)用程序的引出函數(shù)將一個(gè)句柄作為參數(shù)傳送給應(yīng)用程序,應(yīng)用程序一旦獲得了一個(gè)確定項(xiàng)的句柄,便可在WINDOWS環(huán)境下的任何地方對這個(gè)句柄進(jìn)行操作。其實(shí)句柄的大量使用已經(jīng)影響到了每一個(gè)WINDOWS的程序設(shè)計(jì)。
句柄只有當(dāng)唯一的確定了一個(gè)項(xiàng)目的時(shí)候,它才開始有意義。句柄對應(yīng)著項(xiàng)目表中的一項(xiàng),而只有WINDOWS本身才能直接存取這個(gè)表,應(yīng)用程序只能通過API函數(shù)來處理不同的句柄,舉個(gè)例子來說吧!比如:我們可以為我們的應(yīng)用程序申請一塊內(nèi)存塊,通過調(diào)用API函數(shù)GlobalAlloc,來返回一個(gè)句柄值:
hMem=GlobalAlloc(......);
其實(shí)現(xiàn)在hMem的值只是一個(gè)索引值,不是物理地址,應(yīng)用程序還不能直接存取這塊內(nèi)存。這兒還有一個(gè)話外題,就是,一般情況下我們在編程的時(shí)候,給應(yīng)用程序分配的內(nèi)存都是可以移動(dòng)的或者是可以丟棄的,這樣能使有限的內(nèi)存資源充分利用,所以,在某一個(gè)時(shí)候我們分配的那塊內(nèi)存的地址是不確定的,因?yàn)樗强梢砸苿?dòng)的,所以得先鎖定那塊內(nèi)存塊,這兒應(yīng)用程序需要調(diào)用API函數(shù)GlobalLock函數(shù)來鎖定句柄。如下:
lpMem=GlobalLock(hMem);
這樣應(yīng)用程序才能存取這塊內(nèi)存。
我想現(xiàn)在大家已經(jīng)能對句柄概念有所了解了,我希望我的文章能對大家有所幫助。其實(shí)如果你學(xué)過SDK編程,那對句柄的概念理解會(huì)更好,更深。如果你是直接學(xué)VC6的MFC編程的,建議你看一下SDK編程,這會(huì)對你大有好處。
=== 有關(guān) 句柄或指針的 常用函數(shù)
1. 如何獲取應(yīng)用程序的 實(shí)例句柄? AfxGetInstanceHandle()
????應(yīng)用程序的 實(shí)例句柄保存在CWinAppIm_hInstance 中,可以這么調(diào)用?AfxGetInstancdHandle獲得句柄.
??????Example: HANDLE hInstance=AfxGetInstanceHandle();
2. 如何通過代碼獲得應(yīng)用程序主窗口的 指針? AfxGetMainWnd? GetSafeHwnd() AfxGetAppName()? AfxGetThread
?? 主窗口的 指針保存在CWinThread::m_pMainWnd中,調(diào)用 AfxGetMainWnd實(shí)現(xiàn)。
??【例】???AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最大化.
? 【例】此例的主窗口是對話框,下面的代碼是在另外一個(gè)CFileTreeCtrl 類(子窗)中相關(guān)函數(shù)實(shí)現(xiàn)在主對話框(主窗)中的幾個(gè) 靜態(tài)文本框(子窗)中顯示路徑:
??????????? 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); //向主窗口發(fā)送一個(gè)消息,顯示任務(wù)由主窗完成。
?????????????????????????????????????????????? //在主窗的.cpp中有:ON_MESSAGE(STN_CLICKED, OnSTATICpath3)相關(guān)描述
?????????? //有的函數(shù)必須通過窗口的 句柄 來訪問,我們可以使用下面的方法三
?????????? //CWnd::GetSafeHwnd
?????????? //Returns the window handle for a window
?????????? //HWND GetSafeHwnd( ) const;
?????????? HWND m_hWnd_tree =GetSafeHwnd();//【注】此處得到的只是當(dāng)前窗口(FileTree類)的句柄
?????????? HWND m_hWnd = m_pCWnd->GetSafeHwnd();// 這里才是主窗口的句柄(由主窗指針得到主窗的句柄)
?????????? //BOOL SetWindowText( HWND hWnd, LPCTSTR lpString )
?????????? ::SetWindowText(m_hWnd,"ok2222");//修改主窗口標(biāo)題
?????????? ::SetDlgItemText(m_hWnd,IDC_STATIC_path2,"HWND: "+m_sCurPath);
? 【另】AfxGetThread
????? CWinThread* AfxGetThread( );
????? Return Value:Pointer to the currently executing thread.
3. 如何在程序中獲得其他程序的 圖標(biāo)? 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函數(shù) SHGetFileInfo 或使用 ExtractIcon獲得圖標(biāo)資源的 handle(句柄),
????????(2) SDK函數(shù) SHGetFileInfo獲得有關(guān)文件的 很多信息,如大小圖標(biāo),屬性,類型等.
??????????Example(1): 在程序窗口左上角顯示 NotePad圖標(biāo).
?????????? 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);
??????????????}
?? 【說明】關(guān)于如何得到系統(tǒng)文件的正確路徑,象win.ini system32.ini等的路徑,各種系統(tǒng)中具體的路徑是不一樣的。如:
?????????? 獲得notepad.exe的路徑正規(guī)上來說用GetWindowsDirectory 函數(shù)得到;
?????????? 如果是調(diào)用 win95下的畫筆,應(yīng)該用訪問注冊表的方法獲得其路徑;
?????????? 要作成一個(gè)比較考究的程序,考慮應(yīng)該全面點(diǎn).
?? 【另】
??????????????? HINSTANCE AfxGetResourceHandle( );
??????????????? Return Value:An HINSTANCE handle where the default resources of the application are loaded.
4.?? 有關(guān)取得桌面句柄 GetDesktopWindow()
MSDN中的例子:
// 靜態(tài)函數(shù)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返回的結(jié)果一樣請問為什莫
HWND ChWnd;//子窗口句柄
HWND hwDesktop=::GetDesktopWindow();//取得桌面句柄
ChWnd=::GetWindow(hwDesktop,GW_CHILD);//取得桌面子句柄
CString csTitle,csClass,csTm,mLookstring;
char szBuffer[255];
while(ChWnd!=NULL)//循環(huán)取子句柄的同級句柄
{
??? if(::IsWindowVisible(ChWnd))//判斷是否為可顯示窗口
??? {
???????? ::GetWindowText(ChWnd,csTitle.GetBuffer(255),254);
???????? ::GetClassName(ChWnd,csClass.GetBuffer(255),254);
???????? csTitle.ReleaseBuffer();//標(biāo)題
???????? csClass.ReleaseBuffer();//類名
???????? csTm.Format("%08X:",ChWnd);
???????? if(csTitle=="")
???????? {
?????????????? mLookstring=csTm+csClass;
???????? }else
???????? {
?????????????? mLookstring=csTm+csTitle;
???????? }
???????? //這里的窗口句柄不是同一個(gè)程序吧?(問題所在!)可是為什莫結(jié)果一樣
???????? 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)總是返回當(dāng)前程序運(yùn)行的hInstance,所以你得到的文件名總是一個(gè)。所以你要用枚舉所有"進(jìn)程的程序名"來獲得程序名。
=== 再談句柄于指針的區(qū)別
?許多開始學(xué)習(xí)VC的朋友,最多聽說的兩個(gè)詞莫過于指針和句柄了。
?但是,確經(jīng)常搞不清他們之間的區(qū)別。
?首先,句柄是一個(gè)窗口的標(biāo)志,也就是所有從CWND類繼承下來的,多有句柄這個(gè)成員。
?他能做的,也就是唯一代表一個(gè)桌面上的窗口罷了。而指針是一個(gè)地址,如果它指向了一個(gè)內(nèi)存中的對象,那么就可以對它進(jìn)行任意操作了,當(dāng)然,并不局限于自己的應(yīng)用程序,你如果能夠獲得別的應(yīng)用程序的某個(gè)對象的指針,也可以進(jìn)行操作。然而,如果要獲得指針,首先,必須找到那個(gè)窗口的句柄,然后用函數(shù)FromHandle就可以得到他的指針了。
===? 問題1:
如何在自定義的消息中發(fā)送一個(gè)字符串?例如:
SendMessage(MyWnd,WM_USERDEFINED, 0,0)
如何將字符串Buffer寫入wParam或lParam?
?你可以把字符串的地址傳遞過去,因?yàn)榈刂氛檬?2位。如:
char s[256];
SendMessage(MyWnd,WM_USERDEFINED, (WPARAM) s,0)
接收方只需要將wParam賦給一個(gè)char*就可以了。但此方法只能使用于在一個(gè)進(jìn)程內(nèi)部傳遞數(shù)據(jù)。
===? 問題2:
1.在VC應(yīng)用程序框架中,如何加入自己做的類,如何定義這個(gè)類的對象,我想在鼠標(biāo)點(diǎn)擊某個(gè)菜單項(xiàng)的時(shí)候才生成這個(gè)對象,做得到嗎?(這個(gè)類的構(gòu)造函數(shù)是帶參數(shù)的)。
2.消息發(fā)送函數(shù):
? PostMessage(HWND handle,WM_MYMESSAGE,
????????????? WPARAM wParam,LPARAM lParam)
? 中:
第一個(gè)參數(shù)如何獲得?
如果我的消息是在自己的應(yīng)用程序中生成的,想發(fā)給應(yīng)用程序的窗口讓它顯示某些數(shù)據(jù)(用TextOut函數(shù)),能做到嗎?
(也可以說是這樣的問題:用Appwizard生成應(yīng)用程序框架,在生成的類(如CView)中如何得到窗口的句柄,并放在PostMessage函數(shù)中。)
3.wParam,lParam,在消息響應(yīng)函數(shù)中如何用?vc是怎樣保證這兩個(gè)數(shù)傳到函數(shù)中的?問題比較多,謝謝!
水平: 剛?cè)腴T
回答:
1、這個(gè)問題是肯定的。你可以使用ClassWizard定義類,也可以手工輸入。如果類定義已經(jīng)在某個(gè)文件中,只要使用Project|Add files將文件加入工程就可以了。要想定義類的對象,只要在你的菜單項(xiàng)的相應(yīng)事件中就可以了。如:
{
...
MyClass myObject("Hello");
myObject.MyMethod();
...
}
2、在你自己的程序中傳遞消息當(dāng)然沒有任何問題,只要你知道要調(diào)用的窗口類是從CWnd繼承來的,你就可以使用GetSafeHwnd函數(shù)獲得窗口句柄。不過一般在自己的同一個(gè)程序中有時(shí)不愿意使用自定義消息,因?yàn)樘闊D阃耆梢越o要調(diào)用的類添加一個(gè)成員函數(shù),只要想顯示數(shù)據(jù),直接調(diào)用這個(gè)成員函數(shù)不就可以了?何必使用PostMessage呢?一般只有在程序間調(diào)用,才愿意使用自定義消息。這時(shí),你通常可以使用FindWindow獲得窗口句柄(QA000251 "如何利用FindWindow()函數(shù)查找程序")。
3、對于MFC已經(jīng)定義了消息處理函數(shù)的消息,MFC會(huì)自動(dòng)把wParam和lParam映射為更容易使用的方式。如OnMouseMove( UINT nFlags, CPoint point )。對于MFC不能自動(dòng)處理的函數(shù),如你使用ON_MESSAGE定義消息函數(shù),則MFC會(huì)把wParam和lParam原原本本的傳遞給你的函數(shù),不做任何處理。
===? 一個(gè)未公開的Win32 API函數(shù):GetTaskmanWindow? ()
??? 下例中還用到: GetProcAddress??? GetParent(hWnd)
??????????????????? HMODULE hUser32 = GetModuleHandle("user32");
download
// getaskmanwnd.cpp (Windows NT/2000) // // 利用一個(gè)未公開的Win32 API函數(shù):GetTaskmanWindow, // 對Windows的任務(wù)欄進(jìn)行操作(顯示/隱藏)。這個(gè)函數(shù)返回?fù)碛腥蝿?wù)欄按鈕的窗口句柄。 // // 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 (*argv[1]=='H' || *argv[1]=='h') ShowWindow(GetParent(hWnd),SW_HIDE); else ShowWindow(GetParent(hWnd),SW_SHOW); }總結(jié)
以上是生活随笔為你收集整理的重庆大学光电工程学院 贾旭滨 对 “句柄” “指针” 有下面的描述(AfxGetMainWnd GetSafeHwnd() AfxGetAppName() AfxGetThread)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 正则表达式收藏(五)之微软的正则
- 下一篇: The 2007 Microsoft O