?? visual c++編程技巧.txt
字號:
//TODO-process system menu item
}
else
CMDIFrameWnd:: OnSysCommand (nID, lParam);
}
最后,一個設計良好的UI應用程序應當在系統菜單項加亮時在狀態條顯示一個幫助信息,這可以通過增加一個包含系統菜單基ID的串表的入口來實現。
59、如何確定頂層菜單所占據的菜單行數
這可以通過簡單的減法和除法來實現。首先,用戶需要計算主框窗口的高度和客戶區;其次,從主框窗口的高度中減去客戶區、框邊界以及標題的高度;最后,除以菜單欄的高度。下例成員函數是一個計算主框菜單所占據的行數的代碼實現。
int CMainFrame:: GetMenuRows ()
{
CRect rcFrame,rcClient;
GetWindowRect (rcFrame);
GetClientRect (rcClient);
return (rcFrame.Height () -rcClient.Height ()-
:: GetSystemMetrics (SM_CYCAPTION) -
(:: getSystemMetrics (SM_CYFRAME) *2)) /
:: GetSystemMetrics (SM_CYMENU);
}
60、在用戶環境中如何確定系統顯示元素的顏色
調用SDK函數GetSysColor可以獲取一個特定顯示元素的顏色。下例說明了如何在MFC函數CMainFrameWnd:: OnNcPaint中調用該函數設置窗口標題顏色。
void CMiniFrameWnd:: OnNcPaint ()
{
…
dc.SetTextColor (:: GetSysColor (m_bActive ?
COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
…
}
61、如何查詢和設置系統參數
在Windows 3.1 SDK中介紹過SDK函數SystemParametersInfo,調用該函數可以查詢和設置系統參數,諸如按鍵的重復速率設置、鼠標雙擊延遲時間、圖標字體以及桌面覆蓋位圖等等。
//Create a font that is used for icon titles.
LOGFONT stFont;
:: SystemParametersInfo (SPIF_GETICONTITLELOGFONT,
sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE);
m_font.CreateFontIndirect (&stFont);
//Change the wallpaper to leaves.bmp.
:: SystemParametersInfo (SPI_SETDESKWALLPAPER, 0,
_T (" forest.bmp"), SPIF_UPDATEINIFILE);
62、如何使用一個預定義的Windows光標
調用CWinApp:: LoadStandardCursor并傳送光標標識符。
BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)
{
//Display wait cursor if busy.
if (m_bBusy)
{
SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT));
return TRUE;
}
return CDialog:: OnSetCursor (pWnd. nHitTest,message);
}
63、如何確定當前屏幕分辨率
調用SDK函數GetSystemMetrics,該函數可以檢索有關windows顯示信息,諸如標題大小、邊界大小以及滾動條大小等等。
//Initialize CSize object with screen size.
CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN));
64、如何檢索原先的Task Manager應用程序使用的任務列表
原先的Task Manager應用程序顯示頂層窗口的列表。為了顯示該列表,窗口
必須可見、包含一個標題以及不能被其他窗口擁有。調用CWnd:: GetWindow可以
檢索頂層窗口的列表,調用IsWindowVisible、GetWindowTextLength以及GetOwner
可以確定窗口是否應該在列表中。下例將把TaskManager窗口的標題填充到列表中。
void GetTadkList (CListBox&list)
{
CString strCaption; //Caption of window.
list.ResetContent (); //Clear list box.
//Get first Window in window list.
ASSERT_VALID (AfxGetMainWnd ());
CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST);
//Walk window list.
while (pWnd)
{
// I window visible, has a caption, and does not have an owner?
if (pWnd ->IsWindowVisible () &&
pWnd ->GetWindowTextLength () &&! pWnd ->GetOwner ())
{
//Add caption o window to list box.
pWnd ->GetWindowText (strCaption);
list.AddString (strCaption);
}
//Get next window in window list.
pWnd=pWnd->GetWindow (GW_HWNDNEXT);
}
}
65、如何確定Windows和Windows系統目錄
有兩個SDK函數可以完成該功能。GetWindowsDirectory和GetSystemDirectory,下例說明了如何使用這兩個函數:
TCHAR szDir [MAX_PATH];
//Get the full path of the windows directory.
:: GetWindowsDirectory (szDir, MAX_PATH);
TRACE ("Windows directory %s\n", szDir);
//Get the full path of the windows system directory.
:: GetSystemDirectory (szDir, MAX_PATH);
TRACE ("Windows system directory %s\n", szDir);
66、在哪兒創建臨文件
調用SDK函數GetTemPath可以確定臨時文件的目錄,該函數首先為臨時路徑檢測TMP環境變量:如果沒有指定TMP,檢測TMP環境變量,然后返回到當前目錄。下例說明了如何創建一個臨時文件。
…
//get unique temporary file.
CString strFile;
GetUniqueTempName (strFile);
TRY
{
//Create file and write data.Note that file is closed
//in the destructor of the CFile object.
CFile file (strFile,CFile:: modeCreate | CFile:: modeWrite);
//write data
}
CATCH (CFileException, e)
{
//error opening file
}
END_CATCH
…
Void GetuniqueTempName (CString& strTempName)
{
//Get the temporary files directory.
TCHAR szTempPath [MAX_PATH];
DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath);
ASSERT (dwResult);
//Create a unique temporary file.
TCHAR szTempFile [MAX_PATH];
UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile);
ASSERT (nResult);
strTempName=szTempFile;
}
67、如何訪問桌面窗口
靜態函數CWnd:: GetDesktopWindow 返回桌面窗口的指針。下例說明了MFC函數CFrameWnd::BeginModalStae是如何使用該函數進入內部窗口列表的。
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);
}
…
}
--------------------------------------------------------------------------------
Visual C++編程小技巧之九
68. VC1.5下如何跳到第一事例?
69. 為什么VC++2.0中使用文件對話框會死機?
70. 在VC++1.5中如何new一個大數組?
71. 在VC1.5中,如何得到子窗口在主窗口中的相對坐標?
72. VC1.5 如何調用進程?
73. VC++1.5編Win3.1程序能否實現全局跳轉?
74. 如何在DLL用自定義窗口?
75. 如何讓TOOLTIP的字體變大?
68.VC1.5下如何跳到第一事例?
各位大蝦: CWinApp::InitInstance()中可知是第二事例,但如何在return FALSE;
之前FindWindow()到第一事例呢? 主要困難是:
1).主窗口類名可否得到 ( 主窗口==MainFrame ? 若是,怎知MainFrame類名?
2).Title因含有文檔名, 是一不確定串.
1. 類名是動態的,所以應該不易得到。(不知是否如此?)
類名不是動態的,如果不作處理, MFC 總是使用 AfxFrameOrView 為類名,
只有 MainFrame, 和 View 等等才會用 AfxFrameOrView,
我剛用 spy 看了我的一個程序,主窗口的Class 為 Afx:b:13ce:6:3be7
至于如何注冊自己定義的類,我還沒有學會,望高手指教。
AfxRegisterWndClass()
2. 我用的方法是只查Title中前半部分和你的要求串一致即可,忽略后面的文檔?
FindWindow() 函數需要給定窗口類名和窗口標題(Title),不知你是怎樣做到只查前半部分的?
用EnumWindows()一個窗口一個窗口查,不能用 FindWindow()
這里我有另外一個問題:
找到第一事例的窗口后,如何激活它,使它成為當前窗口?
極小狀態時,才能把它激活出來,否則也是沒有動靜,不知何故?
if (IsIconic(hwndMain))
ShowWindow(hwndMain, SW_RESTORE);
else
SetActiveWindow(hwndMain);
69.關于VC++2.0中使用文件對話框的求助
在VC++2.0中使用了標準文件對話框以后,編譯聯接都能正常通過,而且使用Ctrl+F5執行EXE文件也完全正常,但是一旦用F5調試進入, 使用該對話框的代碼時,Win95就會異常中止,請問各位高手,為什么?
文件對話框,改變了執行程序的當前路徑,從而干擾了調試系統。如果是為了調試,可以使文件對話框定位在當前目錄,并且運行時不要在其中改變目錄。
70.如何用VC2.0編寫能Edit超過64K的類
我要用 VC2.0 編寫一個 Editor, 要求能編輯超過 64K 的文本.我的 Edit 類從 CEdit 類派生出來 , 但編輯超過 64K 的文本就顯示不出來. 原知道在 VC1.5 中 CEdit 類只能編輯小于 64K 的文本,不知 VC2.0 是否也一樣?
.
自己從CWnd類派生,管理內存、輸入、顯示等(其實不累)。至于從CEdit中派生,我也沒有頭緒。
VC2.0會有這事?我沒試過,但我不相信。VC2.0是運行在Win95或WindowsNT 上的開發工具,是Win32的開發工具。Windows 95及NT對應用程序在內存上沒有段的限制,應用程序最多可利用高達4G的內存(包括系統占用)。你所說的限制大概是VC1.5的限制吧。蓋因VC1.5運行于Win16上,每個段不能超過64K。
的確如此,VC2.0 有兩個例子 samples\mfc\multipad 和 samples\mfc\superpad 也是如此。不信你看看。
71.在VC++1.5中如何new一個大數組
我想在用VC++1.5編程時,new一個[512][512]的大數組,卻總是不行.
哪位專家可以指點一下.
選用Larger and Huger模式的庫編譯
我用過Large模式,好象不行呀!我用Huge模式,頭文件編譯時就出錯了!
VC++ 1.5 畢竟是16的, 512*512 是多少?做鏈表好了否則就用VC++2.0, 全32位就不該有這問題了
這樣的做法并不十分好,要分配如此大的內存最好用全局的內存分配函數.直接用指針操作,效率也會提高.
用MFC類不行嗎?如CObArray
請用GlobalAllocPtr和GlobalFreePtr這一對函數,如下:
DWORD dwSize ;;
hpsStr =(char huge *)GlobalAllocPtr( GMEM_MOVEABLE , dwSize ) ;
...
GlobalFreePtr( hpsStr ) ;
不管多大數組,都保證沒有問題。
在VC1.5中,如何得到子窗口在主窗口中的相對坐標?
比較笨的方法是先ClientToScreen轉成屏幕坐標,然后ScreenToClient轉成主窗口坐標,不知有沒有更方便的方法.
MapWindowPoints(hwndChild, hwndParent, (POINT FAR *)lprc, 2)lprc 設成子窗口內的坐標(0,0, width, height)
72.VC1.5 如何調用進程?
我用VC1.52編Windows程序,中間想執行一個其他Windows應用程序,并且讓我的程序掛起等應用程序執行完后再繼續,請問如何實現?
exec( ) 和 spawn( )與Windows不兼容,所以它們肯定不行了.
WinExec()
掛起的一個簡單方法是得到新進程的主窗口句柄,然后進入死循環,直到此句柄變為無效。
不知道還有什么更漂亮一些的手法。
請問,怎么得到進程的主窗口句柄呢?
是呀,我也正想問呢.例如我執行的是PSpice for Windows.用WinExec()
可以如下:
int nWinRun = WinExec("wpspice test.cir", SW_SHOWNORMAL);
可是如何得到新進程的主窗口句柄呢?能不能截取新進程的消息呢
緊接著用 GetActiveWindow() 就可以.
當然還是在win3.1 下才有用....
win95 下由于有輸入的局部化問題,所以只能得到本線程的Activate Window或Focus Window,對于其他情況返回都是NULL.這問題還是不知道怎么辦,alas...
所 以 最 根 本 的 辦 法 是 如 何 讀 寫 Windows 消 息 總 庫 .
哪 位 高 手 看 得 懂 SPY 的 源 程 序 (在 C++ 或 Delphi 之 類 的 Sample 中 有 ).
Use "FindWindow()". according to window title, get window handle.
then use Window Declassing method. that is write your own procedure
to process the message you want to capture. "CallWindowProc() is
executed before DefWindowProc()". (sorry can not type chinese now.)
我在Vc 4.0 下用_exec, _spawn, 以及WinExec都沒問題的!
73.VC++1.5編Win3.1程序能否實現全局跳轉?
setjmp即可,和DOS下一樣。
用Windows API 中的 Catch() 和 Throw() 可能會更好些。不過我也不知道和setjmp有些什么區別。
setjmp 恐怕不行, 它好象只能用來編寫 C 程序,而不能用來編寫 C++ 程序!
我的感覺是,只要是代碼段,可以不受函數和應用的限制,隨便亂跳的。其實是數據段,也可以跳過去的。換句話說,在WINDOW中,可以跳到任何地方,只要我樂意。
74.在DLL用自定義窗口
我在DLL中用如下窗口,
class CMyWin:public CWnd
{
public:
CMyWin() ;
} ;
CMyWin::CMyWin()
{
if( !CreateEx( WS_EX_TOPMOST ,
AfxRegisterWndClass( CS_SAVEBITS ) ,
"mywin" , WS_POPUP ,
0 , 0 , 100 , 100 , NULL , NULL ) )
AfxMessageBox( "CreateEx error" ) ;
}
請問有誰知道是什么原因?誰在DL
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -