vc 小技巧

. 內存分配問題
1. 變量未初始化。
爲debug中會自動給變量初始化found=FALSE,而在release版中
則不會。所以儘可能的給變量、類或結構初始化。
2. 數據溢出的問題
如:char buffer[10];
int counter;
lstrcpy(buffer, "abcdefghik");
在debug版中buffer的NULL覆蓋了counter的高位,但是除非counter>16M,什麼問題也沒
有。但是在release版中,counter可能被放在寄存器中,這樣NULL就覆蓋了buffer下面
的空間,可能就是函數的返回地址,這將導致ACCESS ERROR。
3. DEBUG版和RELEASE版的內存分配方式是不同的 。如果你在DEBUG版中申請
ele 爲 6*sizeof(DWORD)=24bytes,實際上分配給你的是32bytes(debug版以32bytes
爲單位分配), 而在release版,分配給你的就是24bytes(release版以8bytes爲單位
),所以在debug版中如果你寫ele[6],可能不會有什麼問題,而在release版中,就有A
CCESS VIOLATE。
II. ASSERT和VERIFY
1. ASSERT在Release版本中是不會被編譯的。
假如你在這些語句中加了程序中必須要有的代

比如
ASSERT(pNewObj = new CMyClass);
pNewObj->MyFunction();
這種時候Release版本中的pNewObj不會分配到空間
所以執行到下一個語句的時候程序會報該程序執行了非法操作的錯誤。這時可以用VERIFY
III. 參數問題:
自定義消息的處理函數,必須定義如下:
afx_msg LRESULT OnMyMessage(WPARAM, LPARAM);
返回值必須是HRESULT型,否則Debug會過,而Release出錯
IV. 內存分配
保證數據創建和清除的統一性:如果一個DLL提供一個能夠創建數據的函數,那麼這個D
LL同時應該提供一個函數銷燬這些數據。數據的創建和清除應該在同一個層次上。
V. DLL的災難
人們將不同版本DLL混合造成的不一致性形象的稱爲 “動態連接庫的地獄“(DLL Hell)
如果你的程序使用你自己的DLL時請注意:
1. 不能將debug和release版的DLL混合在一起使用。debug都是debug版,releas
e版都是release版。
解決辦法是將debug和release的程序分別放在主程序的debug和release目錄下
2. 千萬不要以爲靜態連接庫會解決問題,那隻會使情況更糟糕
VI. RELEASE板中的調試 :
1. 將ASSERT() 改爲 VERIFY() 。找出定義在"#ifdef _DEBUG"中的代碼,如果
在RELEASE版本中需要這些代碼請將他們移到定義外。查找TRACE(...)中代碼,因爲這些
代碼在RELEASE中也不被編譯。 請認真檢查那些在RELEASE中需要的代碼是否並沒有被便
宜。
2. 變量的初始化所帶來的不同,在不同的系統,或是在DEBUG/RELEASE版本間
都存在這樣的差異,所以請對變量進行初始化。
3. 是否在編譯時已經有了警告?請將警告級別設置爲3或4,然後保證在編譯時沒
有警告出現.
VII. 將Project Settings" 中 "C++/C " 項目下優化選項改爲Disbale(Debug)。編
譯器的優化可能導致許多意想不到的錯誤,請參考[url]http://www.pgh.net/~newcomer/deb[/url]
ug_release.htm
1. 此外對RELEASE版本的軟件也可以進行調試,請做如下改動:
在"Project Settings" 中 "C++/C " 項目下設置 "category" 爲 "General" 並且將"D
ebug Info"設置爲 "Program Database"。
在"Link"項目下選中"Generate Debug Info"檢查框。
"Rebuild All"
如此做法會產生的一些限制:
無法獲得在MFC DLL中的變量的值。
必須對該軟件所使用的所有DLL工程都進行改動。
*************************************************************
*******句柄是一個標識符,是拿來標識對象或者項目*****
的,它就象我們的姓名一樣,每個人都會有一個,不同的人的姓名不一樣,但是,也可
能有一個名字和你一樣的人。從數據類型上來看它只是一個16位的無符號整數。應用程
序幾乎總是通過調用一個WINDOWS函數來獲得一個句柄,之後其他的WINDOWS函數就可以
使用該句柄,以引用相應的對象
通用的句柄,就是HANDLE,比如下面的語句:
HINSTANCE hInstance;
可以改成:
HANDLE hInstance;

一般情況下我們在編程的時候,給應用程序分配的
內存都是可以移動的或者是可以丟棄的,這樣能使有限的內存資源充分利用,所以,在
某一個時候我們分配的那塊內存的地址是不確定的,因爲他是可以移動的,所以得先鎖
定那塊內存塊,這兒應用程序需要調用API函數GlobalLock函數來鎖定句柄。如下:
lpMem=GlobalLock(hMem);
這樣應用程序才能存取這塊內存。
**********************************************************
要使程序的主窗口不可見,並且不在任務欄上出現任務按鈕,要做到這兩點,需分
別設置主邊框窗口的風格和擴展風格:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

cs.style =WS_POPUP;//使主窗口不可見

cs.dwExStyle |=WS_EX_TOOLWINDOW;//不顯示任務按鈕

return CFrameWnd::PreCreateWindow(cs);
}
*************************************************
**CString str = "Hello/r/nHow are you/r/n";
: 爲什麼pDC->TextOut(0, 0, str);顯示時不能夠自動換行?
如果你的視圖類是CEditView,這樣做是行的通的
但是,如果在CView裏面,這樣就不行,這也很容易理解
CView裏面沒有行的概念,它就像按象素編址的白紙(一個二維平面)
在白紙上換行,顯然是行不通的,因爲它不知道下一行的具體位置
*************************************
*我想在子線程中直接給視圖窗口繪圖,而不調用視圖類的函數OnDraw(),
在子線程中獲得資源,
可以在子線程的構造函數中傳入CMyThread(CWnd* pWnd,HDC hDC,。。)
這樣,在主線程中創建子線程時 mythread(this,m_pDC->m_hDC)
其中m_pDC=m_pDC=new CClientDC(this);
**********************************
*我在程序中需要生成隨機數,
: 但是rand()生成的是0~指定的數之間的隨機數
: 例如我想生成10~20之間的5個隨機數,應該如何做?
int result[5];
srand();
for(int i=0;i<5;i++)
{
result[i]=rand()%11+10;
srand();
}
**************************************
*VC中讓程序發出聲因
beep()
********************************
*獲取當前屏幕分辨率
int nScreenWidth=GetSystemMetrics(SM_CXSCREEN);
int nScreenHeight=GetSystemMetrics(SM_CYSCREEN);
************************************
*把消息從一個view發到另外一個view
在CWinApp裏面保存view的指針。然後再任意地方就可以通過AfxGetApp()調用獲得
view的指針。That is ok!
***********************************
*如何在視圖類函數中得到HDC句柄
得到可以用GetDC,釋放用ReleaseDC,句柄是CDC的成員變量
返回的是CDC對象,但裏面有一個成員變量,好像是m_hCDC之類的
是句柄
*********************************
*註冊控件
regsvr32
-**************************************
*CTypePtrArray跟CObArray本質區別
CTypePtrArray有兩種基本框架類型,CObArray和CPtrArray,裏面的數據類型可以是對象
或者指向對象的指針;所以,它是一個模板類,它的可串行化依賴於它到底是以CObArray
還是以CPtrArray爲基本框架,它是類型安全的.
CObArray,顧名思義,是對象的數組,所以裏面是存放對象的.它不是模板類,可串行化,
不是類型安全的.
**************************************
*vc中的extern "c" 如何使用?
發信站: 武漢白雲黃鶴站 (2003年05月16日21:57:11 星期五), 站內信件

假設某個C 函數的聲明如下:
void foo(int x, int y);
該函數被C 編譯器編譯後在庫中的名字爲_foo,而C++編譯器則會產生像_foo_int_int
之類的名字用來支持函數重載和類型安全連接。由於編譯後的名字不同,C++程序不能
直接調用C 函數。C++提供了一個C 連接交換指定符號extern“C”來解決這個問題。
例如:
extern “C”
{
void foo(int x, int y);
. // 其它函數
}
或者寫成
extern “C”
{
#include “myheader.h”
. // 其它C 頭文件
}
這就告訴C++編譯譯器,函數foo 是個C 連接,應該到庫中找名字_foo 而不是找
_foo_int_int。C++編譯器開發商已經對C 標準庫的頭文件作了extern“C”處理,
*****************************************************
*VC++下怎樣設置棧的大小
方法一:STACKSIZE 定義.def文件

語法:STACKSIZE reserve[,commit]
reserve:棧的大小;commit:可選項,與操作系統有關,在NT上只一次分配物理內存
的大小

方法二:設定/STACK

打開工程,依次操作菜單如下:Project->Setting->Link,在Category 中選中Outpu
t,然後
在Reserve中設定堆棧的最大值和commit。

注意:reserve默認值爲1MB,最小值爲4Byte;commit是保留在虛擬內存的頁文件裏面,它
設置的較
大會使棧開闢較大的值,可能增加內存的開銷和啓動時間
**********************************************************
*鼠標移動到適當的位置時改變光標
void CM_curosrView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetCursor(Cross);
//


CView::OnMouseMove(nFlags, point);
}


其中HCURSOR Cross在構造函數中被初始化成
Cross = AfxGetApp()->LoadStandardCursor(IDC_CROSS);


只要移動,即爲十字標
********************************************************
*如何發送一個關於某個按鈕單擊的消息
試試這兩種:
1、GetDlgItem(IDOK)->PostMessage(BM_CLICK,0,0);
這種是某位高人說的,沒試過。這種是直接發送給按鈕窗口的,是窗口消息。

2、PostMessage(WM_COMMAND,IDOK|BN_CLICKED<<16,GetDlgItem(IDOK)->m_hWnd);
這個是我自己找的一種方法。這個是發送給按鈕父窗口的,是通知消息。
******************************************************
*什麼函數能獲取本地IP
雖然感覺很濫,直接調用ipconfig。
這個程序肯定是每臺機器有得,
windows自己保證,所以你調用就可以方便獲得了。
**********************************
*得到windows和system目錄路徑的函數
getwindowsdirectory
getsystemdirectory
***********************************
1:使用vc開發項目時,
常會遇到這種情況:
即明明只改動了一個文件,卻要把整個項目全部重新編譯連接一次。
剛剛連接好,一運行,又提示重新編譯連接一次。非常討厭。
這是因爲出現了 未來文件 的緣故。(vc5的bug?)
解決方法:找出對應文件夾下的debug目錄,將未來文件全部delete,
再rebuild all一次。(未來 文件即其創建和修改時間都比系統時間靠後)

2:
有時,workspace中的classview顯示混亂。其表現如下:
1:添加的成員變量或函數不能顯示;
2:即使顯示出來了變量或函數,雙擊後不能跳至正確的位置。
解決方法:
刪除.ncb文件,再rebuld all.

3:
如何幹淨的刪除一個類?
1:先從workspace中的FileView中刪除對應的.h和.cpp文件。
2.再關閉項目,從實際的文件夾中刪除對應的.h和.cpp文件。
3.災刪除.clw文件。
打開項目,rebuld all。

4:
初學者常有這樣的疑惑:
直接望工程文件里加入一個CPP原文件再編譯連接的話
老是提示沒有找到預編譯頭
解決方法:
#include "stdafx.h"

5:
如何向項目中加入自己定義的類?
方法很多,介紹一個簡便的:
選擇Insert/New Class菜單
彈出對話框;
選擇Class Type爲generic;
輸入類名。
當然,也可以自己決定該類的基類
6. 通過DLL共享變量
a. 用#pragma data_seg(“segname”) 創建一個節
#pragma data_seg(“share”)
LONG g_lShareData=0;
#pragma data_seg()
b. 在連接器的命令行中使用/SECTION:name attributes開關
//SECTION:share,RWS
或在源代碼中嵌入連接開關:
#pragma comment(linker,”/SECTION:share,RWS”)

7. 動態連接庫的隱式連接
a. DLL輸出函數的頭文件:輸出函數前加_declspec(dllexport);EXE輸入函數的頭文件:
輸入函數前加_delcspec(dllimport)。
b. 在EXE工程項目設置的Link頁面的Object/Libaray Modules 中添加DLL對應的LIB文件(
該文件是在生成DLL的同時生成的)。

8. 用FindFirstChangeNotification(…)來檢測文件系統的變化。
先用FindFirstChangeNotification登記要監測的文件夾,然後用WaitForSingleObject等
函數來等待文件變化事件的到來,並處理該時間。在處理後如果需要繼續監測,那麼還要
調用FindNextChangeNotification(…)。
***********************************************
*怎樣在c++裏得到文件長度
HANDLE hFile;
hFile = CreateFile(lpcTheFile, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (hFile != INVALID_HANDLE_VALUE) {
DWORD dwFileSize = GetFileSize(hFile, NULL);
CloseHandle(hFile);
}
*********************************************
*MessageBox()與AfxMessageBox()的區別
C 中可調用的涵數大致可分三類:
1.類自己的涵數,只對類自己的數據成員有作用;
2.AFX小組在設計 Application Framworks 時設計的全局函數,多冠在Afx前綴,在包含
了MFC庫/框架的工程中可用;
3.Windows API的全局函數。對所有Windows平臺下的程序設計都可以調用,如Vb,Vc,De
phi等等。
你說的 MessageBox是屬於 CWnd 類的成員函數,只能在 CWnd 和CWnd的派生類的對象中
調用;AfxMessageBox則可在任何地方調用。
另外對應的還有: ::MessageBox()這個windows API的全局函數。
上述中1和3一般有一個區別,就是1要比3少一個參數,即窗口句柄。大家知道,這個句
柄是通過 this 指針曲折轉換得到的,不用程序員操心了。
*************************************************
*VC開發小技巧20個
發信站: 武漢白雲黃鶴站 (2002年11月29日12:56:15 星期五), 轉信

一、打開CD-ROM
mciSendString("Set cdAudio door open wait",NULL,0,NULL);
二、關閉CD_ROM
mciSendString("Set cdAudio door closed wait",NULL,0,NULL);
三、關閉計算機
OSVERSIONINFO OsVersionInfo; //包含操作系統版本信息的數據結構
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo); //獲取操作系統版本信息
if(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
//Windows98,調用ExitWindowsEx()函數重新啓動計算機
DWORD dwReserved;
ExitWindowsEx(EWX_REBOOT,dwReserved); //可以改變第一個參數,實現註銷用戶、
//關機、關閉電源等操作
// 退出前的一些處理程序
}
四、重啓計算機
typedef int (CALLBACK *SHUTDOWNDLG)(int); //顯示關機對話框函數的指針
HINSTANCE hInst = LoadLibrary("shell32.dll"); //裝入shell32.dll
SHUTDOWNDLG ShutDownDialog; //指向shell32.dll庫中顯示關機對話框函數的指針
if(hInst != NULL)
{
//獲得函數的地址並調用之
ShutDownDialog = (SHUTDOWNDLG)GetProcAddress(hInst,(LPSTR)60);
(*ShutDownDialog)(0);
}
五、枚舉所有字體
LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET; // Initialize the LOGFONT structure
strcpy(lf.lfFaceName,"");
CClientDC dc (this);
// Enumerate the font families
::EnumFontFamiliesEx((HDC) dc,&lf,
(FONTENUMPROC) EnumFontFamProc,(LPARAM) this,0);
//枚舉函數
int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf,
LPNEWTEXTMETRIC lpntm,DWORD nFontType,long lparam)
{
// Create a pointer to the dialog window
CDay7Dlg* pWnd = (CDay7Dlg*) lparam;
// add the font name to the list box
pWnd ->m_ctlFontList.AddString(lpelf ->elfLogFont.lfFaceName);
// Return 1 to continue font enumeration
return 1;
}
其中m_ctlFontList是一個列表控件變量
六、一次只運行一個程序實例,如果已運行則退出
if( FindWindow(NULL,"程序標題")) exit(0);
七、得到當前鼠標所在位置
CPoint pt;
GetCursorPos(&pt); //得到位置
八、上下文菜單事件觸發事件:OnContextMenu事件
九、顯示和隱藏程序菜單
CWnd *pWnd=AfxGetMainWnd();
if(b_m) //隱藏菜單
{
pWnd->SetMenu(NULL);
pWnd->DrawMenuBar();
b_m=false;
}
else
{
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME); ////顯示菜單 也可改變菜單項
pWnd->SetMenu(&menu);
pWnd->DrawMenuBar();
b_m=true;
menu.Detach();
}
十、獲取可執行文件的圖標
HICON hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);
if (hIcon &&hIcon!=(HICON)-1)
{
pDC->DrawIcon(10,10,hIcon);
}
DestroyIcon(hIcon);
十一、窗口自動靠邊程序演示
BOOL AdjustPos(CRect* lpRect)
{//自動靠邊
int iSX=GetSystemMetrics(SM_CXFULLSCREEN);
int iSY=GetSystemMetrics(SM_CYFULLSCREEN);
RECT rWorkArea;
BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rWorkAre
a, 0);
CRect rcWA;
if(!bResult)
{//如果調用不成功就利用GetSystemMetrics獲取屏幕面積
rcWA=CRect(0,0,iSX,iSY);
}
else
rcWA=rWorkArea;
int iX=lpRect->left;
int iY=lpRect->top;
if(iX < rcWA.left + DETASTEP && iX!=rcWA.left)
{//調整左
//pWnd->SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);
lpRect->OffsetRect(rcWA.left-iX,0);
AdjustPos(lpRect);
return TRUE;
}
if(iY < rcWA.top + DETASTEP && iY!=rcWA.top)
{//調整上
//pWnd->SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);
lpRect->OffsetRect(0,rcWA.top-iY);
AdjustPos(lpRect);
return TRUE;
}
if(iX + lpRect->Width() > rcWA.right - DETASTEP && iX !=rcWA.right-lpRect->W
idth())
{//調整右
//pWnd->SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);
lpRect->OffsetRect(rcWA.right-lpRect->right,0);
AdjustPos(lpRect);
return TRUE;
}
if(iY + lpRect->Height() > rcWA.bottom - DETASTEP && iY !=rcWA.bottom-lpRect
->Height())
{//調整下
//pWnd->SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);
lpRect->OffsetRect(0,rcWA.bottom-lpRect->bottom);
return TRUE;
}
return FALSE;
}
//然後在ONMOVEING事件中使用所下過程調用
CRect r=*pRect;
AdjustPos(&r);
*pRect=(RECT)r;
十二、給系統菜單添加一個菜單項
給系統菜單添加一個菜單項需要進行下述三個步驟:
首先,使用Resource Symbols對話(在View菜單中選擇Resource Symbols...可以顯
示該對話)定義菜單項ID,該ID應大於0x0F而小於0xF000;
其次,調用CWnd::GetSystemMenu獲取系統菜單的指針並調用CWnd:: Appendmenu將菜單
項添加到菜單中。下例給系統菜單添加兩個新的
int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{

//Make sure system menu item is in the right range.
ASSERT(IDM_MYSYSITEM<0xF000);
//Get pointer to system menu.
CMenu* pSysMenu=GetSystemMenu(FALSE);
ASSERT_VALID(pSysMenu);
//Add a separator and our menu item to system menu.
CString StrMenuItem(_T ("New menu item"));
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_MYSYSITEM, StrMenuItem);

}
十三、運行其它程序
//1、運行EMAIL或網址
char szMailAddress[80];
strcpy(szMailAddress,"mailto:[email protected]");
ShellExecute(NULL, "open", szMailAddress, NULL, NULL, SW_SHOWNORMAL);
//2、運行可執行程序
WinExec("notepad.exe",SW_SHOW); //運行計事本
十四、動態增加或刪除菜單
1、 增加菜單
//添加
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //得到主菜單
(mainmenu->GetSubMenu (0))->AppendMenu (MF_SEPARATOR);//添加分隔符
(mainmenu->GetSubMenu (0))->AppendMenu(MF_STRING,ID_APP_ABOUT,_T("Always on
&Top")); //添加新的菜單項
DrawMenuBar(); //重畫菜單
2、 刪除菜單
//刪除
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //得到主菜單
CString str ;
for(int i=(mainmenu->GetSubMenu (0))->GetMenuItemCount()-1;i>=0;i--) //取得菜
單的項數。
{
(mainmenu->GetSubMenu (0))->GetMenuString(i,str,MF_BYPOSITION);
//將指定菜單項的標籤拷貝到指定的緩衝區。MF_BYPOSITION的解釋見上。
if(str=="Always on &Top") //如果是剛纔我們增加的菜單項,則刪除。
{
(mainmenu->GetSubMenu (0))->DeleteMenu(i,MF_BYPOSITION);
break;
}
十五、改變應用程序的圖標
靜態更改: 修改圖標資源IDR_MAINFRAME。它有兩個圖標,一個是16*16的,另一個是3
2*32的,注意要一起修改。
動態更改: 向主窗口發送WM_SETICON消息.代碼如下:
HICON hIcon=AfxGetApp()->LoadIcon(IDI_ICON);
ASSERT(hIcon);
AfxGetMainWnd()->SendMessage(WM_SETICON,TRUE,(LPARAM)hIcon);
十六、另一種改變窗口標題的方法
使用語句 CWnd* m_pCWnd = AfxGetMainWnd( ),然後,再以如下形式調用SetWindowTe
xt()函數:
SetWindowText( *m_pCWnd,(LPCTSTR)m_WindowText);// m_WindowText可以是一個CSt
ring類的變量。
十七、剪切板上通過增強元文件拷貝圖像數據
下面代碼拷貝通過元文件拷貝圖像數據到任何應用程序,其可以放置在CView派生類的函
數中。
CMetaFileDC * m_pMetaDC = new CMetaFileDC();
m_pMetaDC->CreateEnhanced(GetDC(),NULL,NULL,"whatever");
//draw meta file
//do what ever you want to do: bitmaps, lines, text...
//close meta file dc and prepare for clipboard;
HENHMETAFILE hMF = m_pMetaDC->CloseEnhanced();
//copy to clipboard
OpenClipboard();
EmptyClipboard();
::SetClipboardData(CF_ENHMETAFILE,hMF);
CloseClipboard();
//DeleteMetaFile(hMF);
delete m_pMetaDC;
十八、剪切板上文本數據的傳送
把文本放置到剪接板上:
CString source;
//put your text in source
if(OpenClipboard())
{
HGLOBAL clipbuffer;
char * buffer;
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, LPCSTR(source));
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}
從剪接板上獲取文本:
char * buffer;
if(OpenClipboard())
{
buffer = (char*)GetClipboardData(CF_TEXT);
//do something with buffer here
//before it goes out of scope
}
CloseClipboard();
十九、將捕捉屏幕圖像到剪切版中
void CShowBmpInDlgDlg::OnCutScreen()
{
ShowWindow(SW_HIDE);
RECT r_bmp={0,0,::GetSystemMetrics(SM_CXSCREEN),
::GetSystemMetrics(SM_CYSCREEN)};
HBITMAP hBitmap;
hBitmap=CopyScreenToBitmap(&r_bmp);
//hWnd爲程序窗口句柄
if (OpenClipboard())
{
EmptyClipboard();
SetClipboardData(CF_BITMAP, hBitmap);
CloseClipboard();
}
ShowWindow(SW_SHOW);
}
HBITMAP CShowBmpInDlgDlg::CopyScreenToBitmap(LPRECT lpRect)
{
//lpRect 代表選定區域
{
HDC hScrDC, hMemDC;
// 屏幕和內存設備描述表
HBITMAP hBitmap, hOldBitmap;
// 位圖句柄
int nX, nY, nX2, nY2;
// 選定區域座標
int nWidth, nHeight;
// 位圖寬度和高度
int xScrn, yScrn;
// 聊環直媛?
// 確保選定區域不爲空矩形
if (IsRectEmpty(lpRect))
return NULL;
//爲屏幕創建設備描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//爲屏幕設備描述表創建兼容的內存設備描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 獲得選定區域座標
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 獲得 聊環直媛?
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//確保選定區域是可見的
if (nX<0)
nX = 0;
if (nY<0)
nY = 0;
if (nX2>xScrn)
nX2 = xScrn;
if (nY2>yScrn)
nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 創建一個與屏幕設備描述表兼容的位圖
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位圖選到內存設備描述表中
hOldBitmap =(HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕設備描述表拷貝到內存設備描述表中
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
hScrDC, nX, nY, SRCCOPY);
//得到屏幕位圖的句柄
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位圖句柄
return hBitmap;
}
}
二十、如何將位圖縮放顯示在Static控件中
//在Staic控件內顯示位圖
void CShowBmpInDlgDlg::ShowBmpInStaic()
{
CBitmap hbmp;
HBITMAP hbitmap;
//將pStatic指向要顯示的地方
CStatic *pStaic;
pStaic=(CStatic*)GetDlgItem(IDC_IMAGE);
//裝載資源 MM.bmp是我的一個文件名,用你的替換
hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),"MM.bmp",
IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
hbmp.Attach(hbitmap);
//獲取圖片格式
BITMAP bm;
hbmp.GetBitmap(&bm);
CDC dcMem;
dcMem.CreateCompatibleDC(GetDC());
CBitmap *poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);
CRect lRect;

pStaic->GetClientRect(&lRect);
lRect.NormalizeRect();
//顯示位圖
pStaic->GetDC()->StretchBlt(lRect.left ,lRect.top ,lRect.Width(),lRect.Heigh
t(),
&dcMem,0 ,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
dcMem.SelectObject(&poldBitmap);
}
***************************************
*如何在程序裏知道硬盤的剩餘空間
CString s;
ULONGLONG
ullFreeBytesAvailableToCaller,
ullTotalNumberOfBytes,
ullTotalNumberOfFreeBytes;
if(GetDiskFreeSpaceEx(
_T("C://"),
(PULARGE_INTEGER)&ullFreeBytesAvailableToCaller,
(PULARGE_INTEGER)&ullTotalNumberOfBytes,
(PULARGE_INTEGER)&ullTotalNumberOfFreeBytes))
{
s.Format(_T("磁盤剩餘空間:%lKB"), ullTotalNumberOfFreeBytes/1024);
MessageBox(s);
}
***********************************************
*如何unable對話框上的x
標 題: Re: 如何unable對話框上的x?
發信站: 武漢白雲黃鶴站 (2002年08月13日01:33:12 星期二), 轉信

CMenu *pMenu=this->GetSystemMenu(FALSE);
pMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND|MF_GRAYED);

【 在 eleven (eleven) 的大作中提到: 】
: 但保留最大化和最小化按鈕?
: 謝了先!
**********************************
*怎麼把CString型的數字轉變成int
先得到CString的字串char*,
再用atoi
******************************************
*已知HDC,怎麼得到CDC
static CDC* PASCAL FromHandle( HDC hDC );
CDC* GetDC( );
***********************************
*把某個盤設爲共享,有這樣的函
NetShareAdd
**************************************
*如何映射網絡驅動器
WNetAddConnection
**********************
*註冊表中有沒有啓動加載DLL的設置
HKEY_LOCAL_MACHINE/Software/Microsoft
/Windows/CurrentVersion/SharedDLLs.好像是的吧
*********************************
*怎樣把進程註冊爲服務
HKEY_CLASSES_ROOT/APPID
******************************
*在應用程序類中,有個InitInstance()函數,
: 在這個函數中假如這樣的兩行:
: RegisterShellFileType();
: EnableShellOpen();
RegisterShellFileType()作用就是允許文件關聯。如notepad可以打開text文本文件,

如果你創建了一個新的文件類型,操作系統默認以你的程序
打開你創建的文件類型。
EnableShellOpen():當你拖動文件到你程序時,可以打開相應的文檔。入IE,當你拖動文
檔到IE
時可以打開該文檔。
*******************************
*怎麼得到DLL的輸出函數
使用dumpbin.exe


不過沒有參************
***************************************
*誰給我解答一下SPY++用法的幾點疑惑
發信站: 武漢白雲黃鶴站 (Wed Aug 30 09:32:35 2000) , 站內信件

【 在 jinyix (jyx) 的大作中提到: 】
: (1)用 find window 看到 子窗口和主窗口properties中
: 的Instance handle怎麼會不一樣?
: 我想都應該是程序的實例句柄(唯一)。
:
:
: (2)WINDOW View中有很多"Default IME" IME
: 表示什麼窗口?
首先必須明白的是: 對於按鈕,列表框等等東西,他們都是一個窗口,只是窗口
的風格不一樣,因此它們也有自己句柄.
Default IME是指缺省的輸入法,每個窗口都有一個缺省的輸入法.
**********************************************
*如何調用DLL中的資源(位圖...)
使用方法如下:
HMODULE hMoudle = (HMODULE)LoadLibrary("XXXXX.dll");
HRSRC hRes = FindResource(hModule,MAKEINTRESOURCE(IDB_MYBITMAP),"RT_BITMAP")
;
HBITMAP hBmp = (HBITMAP)LoadResource(hModule,hRes);
Remarks
Both Windows 95 and Windows NT automatically free resources. You do not need
to call the FreeResource function to free a resource loaded by using the Lo
adResource function.
但是這一句是需要的:
FreeLibrary(hMoudle);
*****************************************
*如何在VC程序中執行*.lnk文件
Try ShellExecuteEx().
************************************
*把指定目錄下的所有文件拷到另一個指定目
SHFILEOPSTRUCT fileop;
CString Title = "Copy Files";
fileop.hwnd = this->m_hWnd;
fileop.pFrom = "C:/Winnt/*.*";
fileop.pTo = "d:/temp"
fileop.wFunc = FO_COPY;
fileop.fFlags = FOF_NOCONFIRMMKDIR;
fileop.lpszProgressTitle = (LPCSTR)Title;
SHFileOperation(&fileop);

********************************************
* 怎麼得到主窗口的句柄
AfxGetMainWnd()->GetSafeHwnd()
******************************************
*動態的聲明一個二維數組(兩個維數都未知)
double ** twoPtrAlloc(LONG h,LONG w)
{
double ** pd;
pd=new double* [h];
if(!pd)
{
return NULL;
}
for (int i=0;i<h;i++)
{
pd[i]=new double[w];
if(!pd[i])
{
return NULL;
}
}
return pd;
}
**************************************
*MDI程序中,在不同的子窗口中切換時系統會產生何種消息?

WM_MDIACTIVATE
****************************************************
*有效的跟蹤WM_PAINT消息
可以在
OnDraw中打印一個自增的數。看看運行時是否進入了
OnDraw中,也可以用MessageBeep聽聽聲音
****************************************
*在非視圖非文檔類中得到視圖指針 MDI
CMainFrame * pFrame=(CMainFrame *)(AfxGetApp()->m_pMainWnd());
ASSERT(pFrame!=NULL);
(CYourView *)pView=(CYourView *)(pFrame->MDIGetActive()->GetActiveView());
ASSERT(pView!=NULL);
**********************************
*VC5中MFC DLL的分類及特點

  在VC5中有三種形式的MFC DLL(在該DLL中可以使用和繼承已有的MFC類)可供選擇,即Regular statically linked to MFC DLL(標準靜態鏈接MFC DLL)和Regular using the shared MFC DLL(標準動態鏈接MFC DLL)以及Extension MFC DLL(擴展MFC DLL)。第一種DLL的特點是,在編譯時把使用的MFC代碼加入到DLL中,因此,在使用該程序時不需要其他MFC動態鏈接類庫的存在,但佔用磁盤空間比較大;第二種DLL的特點是,在運行時,動態鏈接到MFC類庫,因此減少了空間的佔用,但是在運行時卻依賴於MFC動態鏈接類庫;這兩種DLL既可以被MFC程序使用也可以被Win32程序使用。第三種DLL的特點類似於第二種,做爲MFC類庫的擴展,只能被MFC程序使用。

*******************************************
*Win32全局鉤子的運行機制

  鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得到控制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。對每種類型的鉤子由系統來維護一個鉤子鏈,最近安裝的鉤子放在鏈的開始,而最先安裝的鉤子放在最後,也就是後加入的先獲得控制權。要實現Win32的系統鉤子,必須調用SDK中的API函數SetWindowsHookEx來安裝這個鉤子函數,這個函數的原型是HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId);,其中,第一個參數是鉤子的類型;第二個參數是鉤子函數的地址;第三個參數是包含鉤子函數的模塊句柄;第四個參數指定監視的線程。如果指定確定的線程,即爲線程專用鉤子;如果指定爲空,即爲全局鉤子。其中,全局鉤子函數必須包含在DLL(動態鏈接庫)中,而線程專用鉤子還可以包含在可執行文件中。得到控制權的鉤子函數在完成對消息的處理後,如果想要該消息繼續傳遞,那麼它必須調用另外一個SDK中的API函數CallNextHookEx來傳遞它。鉤子函數也可以通過直接返回TRUE來丟棄該消息,並阻止該消息的傳遞。

*************************************************
*在VC5中全局共享數據的實現

  在主文件中,用#pragma data_seg建立一個新的數據段並定義共享數據,其具體格式爲:

  #pragma data_seg ("shareddata")

  HWND sharedwnd=NULL;//共享數據

  #pragma data_seg()

  僅定義一個數據段還不能達到共享數據的目的,還要告訴編譯器該段的屬性,有兩種方法可以實現該目的(其效果是相同的),一種方法是在.DEF文件中加入如下語句:

  SETCTIONS

  shareddata READ WRITE SHARED

  另一種方法是在項目設置鏈接選項中加入如下語句:

  /SECTION:shareddata,rws
***********************************************************
*怎麼由句柄得到指針
CWnd有一個靜態函數叫做FromHandlePermanent(HWND hWnd)
如果是通過窗口句柄得到自己進程內的窗口指針,這個函數將會正常工作
如果是得到其它進程的窗口指針就不對了

創建的窗口在系統中有一張表維護指針和句柄之間的關係
CWnd的FromHandlePermanent(HWND hWnd)就是通過這張表查找到窗口指針的

CHandleMap* pMap = afxMapHWND();//首先取得這張表
CWnd* pWnd = NULL;
if (pMap != NULL)
{
//查找窗口句柄對應的CWnd對象
pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
ASSERT(pWnd == NULL || pWnd->m_hWnd == hWnd);
}
return pWnd;
*********************************************************
*怎麼調試一個Automation服務器
Project->Setting->Debug->Program arguments

加入/Embedding
*********************************************
*如何使窗口在一開始就不可見
看看有沒有WS_HIDE,如果沒有,則加入WS_MINIMIZED,然後在

OnEraseBkGnd的消息裏面加入:
static BOOL bFirst=TRUE;
if(bFirst)
{
bFirst=FALSE;
ShowWindow(SW_HIDE);
return TRUE;
}
************************************************
*.dll如何在VC中應用
如果有這個動態連接庫的調用格式資料的話,問題很簡單.
1)動態連接
LoadLibery()
GetProcessAddress()
2)靜態連接
首先生成這個動態連接庫的引入庫;
再用到這個庫的文件開始加上
#progma comment(lib,"libname");
************************************************
*新式的用CSocket獲得本機地址方法。
CSocket socket;
socket.Create();
socket.Connect("pop3.sina.com.cn", 110);//或連接pop.tom.com等等
CString strAddress;
UINT uPort;
socket.GetSockName( strAddress, uPort);
CClientDC dc(this);
dc.TextOut( 30, 30, "你的IP:" + strAddress);
socket.Close();  
************************************************
*如何用VC創建ODBC數據源,而不是人工在控制面板的ODBC數據源創建?
如建一個爲MyTax的Access 2000數據源,Tax.mdb在D:/
if( !SQLConfigDataSource(
NULL,
ODBC_ADD_DSN, //加在USER DSN,若要加在SYS DSN則爲ODBC_ADD_SYSDSN
"Microsoft Access Driver (*.mdb)",
"DSN = MyTaxDBQ = D://Tax.mdb")
//注意,XXXX.mdb必須爲英文,若爲中文在VC6會報錯的,VC.NET 2003 沒測試過
)
AfxMessageBox("創建失敗!");
 要加上頭文件#include <odbcinst.h>,在Link處加上odbccp32.lib。
************************************************
*怎麼樣用VC調用 regsvr32.exe 命令
WinExec( "regsvr32.exe Test.dll", SW_SHOW);

shellexecute
************************************************
* 隱藏WINDOWS系統任務欄
::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_HIDE);
************************************************
*全屏的實現關鍵代碼
int CX = GetSystemMetrics(SM_CXSCREEN);
int CY = GetSystemMetrics(SM_CYSCREEN);

::MoveWindow(hwnd,0,0,CX,CY,TRUE);
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
********************************
* 怎樣使應用程序窗口在最前
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.dwExStyle|=WS_EX_TOPMOST;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~only add this sentence
return TRUE;
}
********************************
* 去除框架窗口的標題
LONG style=::GetWindowLong(m_wndToolBar,GWL_STYLE);
style&=~(WS_CAPTION);
::SetWindowLong(m_wndToolBar,GWL_STYLE,style);
********************************
* 怎樣除掉工具欄的標題(浮動時出現的)
LONG style=::GetWindowLong(m_wndToolBar.GetParentFrame()->m_hWnd,GWL_STYLE);
style&=~(WS_CAPTION);
::SetWindowLong(m_wndToolBar.GetParentFrame()->m_hWnd,GWL_STYLE,style);
m_wndToolBar.GetParentFrame()->ModifyStyle(0,MFS_MOVEFRAME|MFS_4THICKFRAME|MFS_THICKFRAME);
注意工具欄的父窗口並不是你的CMainFrame!!
********************************
*把cstring對象轉換成普通字符串char
CString str="***********";
char *p=str.GetBuffer(str.GetLength()+1);
********************************
*如何調用DLL中的資源(位圖...)
]使用方法如下:
HMODULE hMoudle = (HMODULE)LoadLibrary("XXXXX.dll");
HRSRC hRes = FindResource(hModule,MAKEINTRESOURCE(IDB_MYBITMAP),"RT_BITMAP")
;
HBITMAP hBmp = (HBITMAP)LoadResource(hModule,hRes);
Remarks
Both Windows 95 and Windows NT automatically free resources. You do not need
to call the FreeResource function to free a resource loaded by using the Lo
adResource function.
但是這一句是需要的:
FreeLibrary(hMoudle);
*****************************************************************
*dll中定義的全局變量和靜態變量,共享變量
dll中定義的全局變量和靜態變量在每一個使用它的exe中都有拷貝,不能
共享。
如果要共享用#pragma data_seg建立一個新的數據
段並定義共享數據,其具體格式爲:
  #pragma data_seg ("shareddata")
  HWND sharedwnd=NULL;//共享數據
  #pragma data_seg()
僅定義一個數據段還不能達到共享數據的目的,還要告訴編譯器該段的屬性,有兩種方
法可以實現該目的(其效果是相同的),
一種方法是在.DEF文件中加入如下語句:
  SETCTIONS
  shareddata READ WRITE SHARED

***********************************************************************
*fopen()打開一個文件後想讀其中第90行的第19個字符
先用fseek(fp,offset,SEEK_SET)把指針定位到要讀取的位置,然後fread(void *buffe
r,int size,int count,FILE *fp);讀取/
到網上搜索一下函數的用法。

***********************************************************************
*如何鎖定鍵盤和鼠標
typedef BOOL ( __stdcall *BlockInput)(BOOL Flag);
BlockInput p = (BlockInput)GetProcAddress(::LoadLibrary("user32.dll"), "
Blo
ckInput");
if (p)
{
p(FALSE); //這樣就可以了
}
***********************************************************************
* 請問如何做一個安裝程序
簡單介紹一下Installshield for VC++6.0的用法如下:?
1。首先按照File->new->project wizard操作生成新project。
2。在File Groups中,對各個文件夾的link右鍵點擊,加入對應的files或者new folder。
3。對Components的included files groups雙擊,彈出對話框,從而導入需要
的File groups中的對應文件夾。你高興也可以修改status text等。
4。加入開始菜單中的快捷操作方式:
在resources中,
shell objects->explorer shell->desktop->start menu->programs,然後對programs
右鍵點擊操作,加入快捷方式,然後對第一行雙擊,會談出對話框,在target中
加入<TARGETDIR>/***.exe,icon選擇0,即可。
5。對media的操作,菜單build->media build wizard...->finish。
6。菜單build->send media to操作導出安裝。
7。如有其他細節如是否壓縮等,自己看一看就明白了。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章