1.使用ModifyStyleEx改變了控件風格無效
答:修改之後,重繪一次,如果還不行的話,再試試看調用SetWindowPos(0,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_DRAWFRAME);
2.動態設置編輯框的ES_PASSWORD無效
答:修改之後,需要調用一次SetPasswordChar('*');
3.如何獲取任務欄小圖標?
答:有網友提出,能不能在程序界面上顯示當前的托盤圖標,這樣更直觀一些。這一點我也曾想到過,也知道奧祕就在TBBUTTON這個結構體的dwData域裏面,可惜這個域的結構在MSDN中沒有描述。我也曾試着發送TB_GETIMAGELIST消息獲取image list的句柄,然後用CImageList::FromHandle加載到CImageList中,但卻都失敗了。
在csdn網友的幫助下,我弄清了dwData的結構,其實dwData有一個這樣的機構,我們命名爲TRAYDATA:
struct TRAYDATA
{
HWND hwnd;
UINT uID;
UINT uCallbackMessage;
DWORD Reserved[2];
HICON hIcon; //托盤圖標的句柄
};
要獲取到這個hIcon,其實很簡單:
//分配虛擬內存
lngAddress = VirtualAllocEx(hProcess, NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE);
//將hProcess進程內,地址爲lngAddress中的內容(大小爲sizeof(TBBUTTON))獲取到tb中
ret = ::ReadProcessMemory(hProcess, LPVOID(long(lngAddress)), &tb, sizeof(TBBUTTON), 0);
//將hProcess進程內,地址爲tb.dwData中的內容(大小爲sizeof(TRAYDATA))獲取到tray中
ret = ::ReadProcessMemory(hProcess, LPVOID(tb.dwData), &tray, sizeof(TRAYDATA), 0);
然後就可以用tray.hIcon索引到這個圖標句柄了
//釋放內存代碼略
4.BeginWaitCursor和EndWaitCursor無效
答:SetCapture();BeginWaitCursor();....EndWaitCursor();ReleaseCapture();
5.打印源碼中文件名和行號常用的宏名是什麼?
答:文件名:__FILE__ 行號:__LINE__
6.如何具體判斷一個字符串中哪個是英文字母
答:函數isalpha
7.在註冊表中如何得到所有安裝了的應用程序程序的信息
答:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall下面的子鍵
8.64位系統下運行32的程序,操作註冊表遭遇重定向問題
答:PVOID OldValue;
HINSTANCE hlibrary;
typedef int (__stdcall * Wow64DisableWow64FsRedirection)(LPVOID);
YWow64DisableWow64FsRedirection f_Wow64DisableWow64FsRedirection = NULL;
typedef int (__stdcall * Wow64RevertWow64FsRedirection)(LPVOID);
Wow64RevertWow64FsRedirection f_Wow64RevertWow64FsRedirection = NULL;
hlibrary = LoadLibrary("Kernel32.dll");
f_Wow64DisableWow64FsRedirection = (Wow64DisableWow64FsRedirection) GetProcAddress(hlibrary,"Wow64DisableWow64FsRedirection");
if(!f_Wow64DisableWow64FsRedirection) { }
f_Wow64DisableWow64FsRedirection (&OldValue);
//這裏寫註冊表操作函數,Open的時候要指定 KEY_WOW64_64KEY標誌
f_Wow64RevertWow64FsRedirection = (Wow64RevertWow64FsRedirection) GetProcAddress(hlibrary,"Wow64RevertWow64FsRedirection");
if(!f_Wow64RevertWow64FsRedirection) { }
f_Wow64RevertWow64FsRedirection (OldValue);
FreeLibrary(hlibrary);
9.怎麼使用系統默認瀏覽器在新窗口打開網頁
答:ShellExecute是我們常用的一個API,可以運行程序,打開網頁。
ShellExecute(NULL, "open", "http://www.csdn.net", NULL,NULL,SW_SHOWMAXIMIZED);
這樣可以打開一個網頁,但不是在新IE中打開,改成下面方式時就可以在一個新的IE中打開網頁了
ShellExecute(NULL, "open", "IEXPLORE", "http://www.csdn.net",NULL,SW_SHOWMAXIMIZED);
10.怎麼清除串口的輸入緩衝
答:PurgeComm(hCom,PURGE_TXABORT ¦ PURGE_RXABORT ¦ PURGE_TXCLEAR ¦ PURGE_RXCLEAR);
11.顯示桌面屬性對話框
答:ShellExecute(GetDesktopWindow()->m_hWnd,"open","control.exe","desk.cpl Display,@Theme","",SW_SHOW );
12.限制Edit只能輸入0-F
答:WNDPROC wpOrigEditProc;
LRESULT CALLBACK wpSubclassEditProc(HWND hDlg,UINT uiMsg,WPARAM wParam,LPARAM lParam);
wpOrigEditProc = (WNDPROC) SetWindowLong(GetDlgItem(IDC_EDIT_DATA)->m_hWnd,
GWL_WNDPROC, (LONG) wpSubclassEditProc);
LRESULT CALLBACK wpSubclassEditProc(HWND hDlg,UINT uiMsg,WPARAM wParam,LPARAM lParam)
{
switch(uiMsg)
{
case WM_CHAR:
if((wParam >= 0x30 && wParam <= 0x39) ||
(wParam >= 0x41 && wParam <= 0x46) ||
(wParam >= 0x61 && wParam <= 0x66) ||
(wParam == 0x08) || wParam == 0x20 || wParam == 0x0D)
{
return CallWindowProc(wpOrigEditProc,hDlg,uiMsg,wParam,lParam);
}
else
{
if(GetKeyState(VK_CONTROL) & 0x8000)
{
return CallWindowProc(wpOrigEditProc,hDlg,uiMsg,wParam,lParam);
}
return true;
}
break;
}
return CallWindowProc(wpOrigEditProc,hDlg,uiMsg,wParam,lParam);
}
13.
//一些幫助函數
//返回當前程序的路徑
//例如c:/abc/abc.exe則返回c:/abc
BOOL GetPath(TCHAR * strPath)
{
TCHAR sDrive[_MAX_DRIVE];
TCHAR sDir[_MAX_DIR];
TCHAR sFilename[_MAX_FNAME],Filename[_MAX_FNAME];
TCHAR sExt[_MAX_EXT];
GetModuleFileName(NULL, Filename, _MAX_PATH);
_tsplitpath(Filename, sDrive, sDir, sFilename, sExt);
_tcscpy(strPath,sDrive);
_tcscat(strPath,sDir);
strPath[_tcslen(strPath)-1] = _T('/0');
return TRUE;
}
//獲得父進程ID,失敗則返回0
DWORD GetPPid()
{
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
DWORD dwPID = GetCurrentProcessId();
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap==(HANDLE)-1)
return (FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
while(pe32.th32ProcessID!=dwPID)
Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return(pe32.th32ParentProcessID);
}
//判斷程序是否以服務運行
BOOL isRuninServices()
{
DWORD dwPPID = GetPPid();
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap ==
(HANDLE)-1)
return (FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
while(pe32.th32ProcessID!=dwPPID)
Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
if(_tcsncicmp(pe32.szExeFile,_T("services.exe"),20)==0)
return TRUE;
else return FALSE;
}
//提升爲調試權限
BOOL EnableDebugPrivilege(BOOL bEnable)
{
BOOL bOk = FALSE;
HANDLE hToken;
if(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
LUID uID;
::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &uID);
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = uID;
tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED
: 0;
::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp),
NULL, NULL);
bOk = (::GetLastError() == ERROR_SUCCESS);
::CloseHandle(hToken);
}
return bOk;
}
//用於在release下輸出調試信息
void KDbgPrint(LPCTSTR lpszFormat, ...)
{
#define _countof(array) (sizeof(array)/sizeof(array[0]))
#ifdef KOUT_DEBUG_STRING
va_list args;
va_start(args, lpszFormat);
int nBuf;
TCHAR szBuffer[512];
nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args);
OutputDebugString(szBuffer);
va_end(args);
#endif
}
//從地址去獲得模塊基址
HMODULE WINAPI ModuleFromAddress(PVOID pv)
{
MEMORY_BASIC_INFORMATION mbi;
if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
{
return (HMODULE)mbi.AllocationBase;
}
else
{
return NULL;
}
}
//獲得DLL自身
BOOL GetDllPath(TCHAR * path)
{
HMODULE hDll = ModuleFromAddress(GetDllPath);
if(hDll==NULL)
return FALSE;
else
{
GetModuleFileName(hDll, path, _MAX_PATH);
return TRUE;
}
}
//格式化string
void format_string(string & str,LPCTSTR
lpszFormat, ...)
{
#define _countof(array) (sizeof(array)/sizeof(array[0]))
va_list args;
va_start(args, lpszFormat);
int nBuf;
TCHAR szBuffer[1024];
nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args);
str = szBuffer;
va_end(args);
}
//提升所需的權限
BOOL EnablePrivilege(LPCTSTR lpName,BOOL bEnable)
{
BOOL bOk = FALSE;
HANDLE hToken;
if(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
LUID uID;
::LookupPrivilegeValue(NULL, lpName, &uID);
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = uID;
tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED
: 0;
::AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp),
NULL, NULL);
bOk = (::GetLastError() == ERROR_SUCCESS);
::CloseHandle(hToken);
}
return bOk;
}
//跳轉到註冊表
void Jump2Reg(string strRegPath,string strKey)
{
//ShellExecute(NULL,NULL,"regjump.exe",strRegPath.c_str(),NULL,SW_SHOW);
ShellExecute(NULL,NULL,"regedit.exe",NULL,NULL,SW_SHOW);
//然後查找註冊表窗口
HWND hMain = NULL;
HWND hTree = NULL;
HWND hList = NULL;
BOOL bFind = FALSE;
for(int i=0;i<10;i++)
{
hMain = FindWindow("RegEdit_RegEdit","註冊表編輯器");
if(hMain!=NULL)
{//查找成功
bFind = TRUE;
break;
}
Sleep(200);
}
if(bFind)
{
hTree = FindWindowEx(hMain,NULL,"SysTreeView32",NULL);
hList = FindWindowEx(hMain,NULL,"SysListView32",NULL);
//選擇樹
SetForegroundWindow(hTree);
SetFocus(hTree);
DWORD dwPID;
GetWindowThreadProcessId(hMain,&dwPID);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
//先把樹給摺疊起,最多30層
for(int i=0;i<30;i++)
{
SendMessage(hTree, WM_KEYDOWN, VK_LEFT, 0);
}
SendMessage(hTree, WM_KEYDOWN, VK_RIGHT, 0);
WaitForInputIdle(hProc, INFINITE);
for(i=0;i<strRegPath.length();i++)
{
if(strRegPath.at(i)=='//')
SendMessage(hTree, WM_KEYDOWN, VK_RIGHT, 0);
else
SendMessage(hTree,WM_CHAR,WPARAM(strRegPath.at(i)),0);
}
WaitForInputIdle(hProc, INFINITE);
//然後到列表了..
SetForegroundWindow(hList);
SetFocus(hList);
Sleep(1000);
SendMessage(hList, WM_KEYDOWN, VK_HOME, 0);
for(i=0;i<strKey.length();i++)
{
SendMessage(hList,WM_CHAR,WPARAM(strKey.at(i)),0);
}
CloseHandle(hProc);
}
return;
}
//////////////////////////////////////////////////////////////////////////
//顯示文件屬性
void ShowProperties(string strPath)
{
SHELLEXECUTEINFO si;
ZeroMemory(&si,sizeof(SHELLEXECUTEINFO));
si.cbSize = sizeof(SHELLEXECUTEINFO);
si.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI
;
si.lpVerb = "properties";
si.lpFile = strPath.c_str();
si.nShow = SW_SHOW;
ShellExecuteEx(&si);
}
//定位文件
void Jump2File(string strPath)
{
string cmd = "/e,/select,"+strPath;
ShellExecute(NULL,NULL,"explorer",cmd.c_str(),NULL,SW_SHOW);
}
14. 動態修改ComboBox的DROPDOWN,DROPDOWNLIST屬性
DWORD theStyle;
HWND theChild;
theChild = ::GetWindow( GetDlgItem(IDC_COMBO1)->m_hWnd , GW_CHILD );
theStyle = GetWindowLong(GetDlgItem(IDC_COMBO1)->m_hWnd, GWL_STYLE );
theStyle &= ~CBS_DROPDOWN;//去掉DROPDOWN
theStyle |= CBS_DROPDOWNLIST; //添加DROPDOWNLIST
::DestroyWindow( theChild );
SetWindowLong(GetDlgItem(IDC_COMBO1)->m_hWnd, GWL_STYLE , theStyle );
15. 如何製作透明窗體
使用SetLayeredWindowAttributes可以方便的製作透明窗體,此函數在w2k以上才支持,而且如果希望直接使用的話,可能需要下載最新的SDK。不過此函數在w2k的user32.dll裏有實現,所以如果你不希望下載巨大的sdk的話,可以直接使用GetProcAddress獲取該函數的指針。
SetLayeredWindowAttributes的函數原型如下:
BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
);
Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Unsupported.(注意了,在win9x裏沒法使用的)
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib.
一些常量:
WS_EX_LAYERED = 0x80000;
LWA_ALPHA = 0x2;
LWA_COLORKEY=0x1;
其中dwFlags有LWA_ALPHA和LWA_COLORKEY
LWA_ALPHA被設置的話,通過bAlpha決定透明度.
LWA_COLORKEY被設置的話,則指定被透明掉的顏色爲crKey,其他顏色則正常顯示.
要使使窗體擁有透明效果,首先要有WS_EX_LAYERED擴展屬性(舊的sdk沒有定義這個屬性,所以可以直接指定爲0x80000).
例子代碼:
在OnInitDialog()加入:
//加入WS_EX_LAYERED擴展屬性
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
HINSTANCE hInst = LoadLibrary("User32.DLL");
if(hInst)
{
typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
MYFUNC fun = NULL;
//取得SetLayeredWindowAttributes函數指針
fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
if(fun)fun(this->GetSafeHwnd(),0,128,2);
FreeLibrary(hInst);
}
稍加修改還可以作出淡出淡入的效果. 注意第三個參數(128)不要取得太小了,爲0的話就完全透明,看不到了。
16.如何使框架窗口的圖標爲動畫顯示
可以用TIMER,但是TIMER不能有效的定時。因爲TIMER發送的是窗口消息,當窗口忙於處理鍵盤、鼠標等消息時就不能及時處理TIMER,會使間隔時間變得很長 。
可以考慮用一個單獨得TIMER線程,用Sleep()定時來解決此問題。
UINT Timer(LPVOID param)
{
HWND hWnd=(HWND)param;
while(1)
{
Sleep(ms);
PostMessage(hWnd,CH_PICTURE,NULL,NULL)
}
}
Sleep(ms)後發送自定義消息。消息處理函數就選擇某一個ICON或BITMAP來顯示。如 :
MyBotton.SetBitmap((HBITMAP)Bitmap[i]);
Bitmap是一個位圖數組,存放有j個位圖。消息處理函數運行一次,i就累加一次,當i==j時,i就回到0;
17.Q 如何處理ComboBox中的回車鍵?避免退出程序?
A 在一般的EDIT中採用的方法是處理PretranlateMessage(),執行代碼
CWnd *pWnd = GetFocus();
if(pWnd != NULL)
{
if(pWnd == GetDlgItem(IDC_EDIT1)
{
...//IDC_EDIT1具有焦點
}
}
但在ComboBox中好象不同,是ComboBox的編輯控件得到了焦點,所以判斷代碼:
BOOL CDlg::PreTranslateMessage(MSG *pMsg)
{
if(pMsg->message==WM_KEYDOWN && pMsg->wParam == VK_RETURN)
{
CWnd *pWnd = GetFocus();
if(pWnd != NULL)
{
if(pWnd->GetParent() == GetDlgItem(IDC_COMBO1)//更改ID
{
return TRUE;
}
}
}
return CDialog::PreTranslateMessage(pMsg);
}
//-------------------------------------------------
Q 動態創建的組合框如何設置下拉列表框的高度?
A m_combo.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL CBC_SORT | CBC_DROPDOWNLIST | WS_TABSTOP, CRect(320,10,580,280),this,114);
//CRect的最後一個參數(這裏是280)就表示下拉大小
//-------------------------------------------------
Q 是否能不選擇下拉列表樣式而禁止用戶輸入值,有什麼方法可以實現?
A 將下拉列表的編輯控件設置爲只讀的,方法如下:
CComboBox *pcombo;
CWnd *pWnd = pcombo->GetWindow(GW_CHILD);
while(pWnd)
{
char classname[256];
::GetClassName(pWnd->m_hWnd,classname,256)
if(strcmp(classname,"edit") == 0)
{
CEdit *pEdit;
pEdit = new CEdit();
pEdit->SubClassWindow(pWnd->m_hWnd);
pEdit->SetReadOnly();
pWnd = pWnd->GetNextWindow();
delete pEdit;
}
if(pWnd)
pWnd = pWnd->GetNextWindow();
}
//-------------------------------------------------
Q ComboBox的自定義彈出菜單,想在右擊組合框的編輯部分的時候彈出菜單?
A 一種方法就是在CCustomCombo的OnCtlColor函數裏進行,生成ComboBox中編輯框的子類,示例:
HBRUSH CCustomCombo::OnCtlColor(CDC *pDC,CWnd *pWnd,UINT nCtlColor)
{
if(nCtlColor == CTLCOLOR_EDIT)
{
if(m_edit.GetSafeHwnd()==NULL)
m_eidt.SubClassWindow(pWnd->GetSafeHwnd());
}
HBRUSH hbr = CComboBox::OnCtlColor(pDC,pWnd,nCtlColor);
return hbr;
}
//其中m_edit是CEdit類的實現,它在WM_RBUTTONUP上顯示右鍵菜單
//-------------------------------------------------
Q 如何給按鈕加位圖
A
對動態創建的按鈕:
CButton button;
button.Create(_T("My Button"),WS_CHILD | WS_VISIBLE | BS_BITMAP,CRect(10,10,60,50),pParentWnd,1);
button.SetBitmap(::LoadBitmap(NULL,MAKEINTRESOURCE(IBM_CHECK)));
或者修改風格:
UINT Style = Button.GetButtonStyle();
Style = Style | BS_BITMAP;
Button.SetBitmap(::LoadBitmap(NULL,MAKEINTRESOURCE(IBM_CHECK)));
//-------------------------------------------------
Q 如何在CButton派生類中以及父對話框中捕獲BN_CLICKED消息?
A 於WM_NOTIFY消息相反,通知消息BN_CLICKED作爲WM_COMMAND消息發送。因此應用程序應該使用ON_CONTROL_REFLECT_EC而不是ON_NOTIFY_REFLECT
//-------------------------------------------------
Q 如何判斷某個對象是否具有當前焦點?
A return (CWnd::GetFocus() == pWnd);
//-------------------------------------------------
Q 如何設置編輯控件的數字限制屬性?
A
long Style = GetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE);
Style |= ES_NUMBER;
SetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE,Style);
//-------------------------------------------------
Q 希望在LISTCTRL中顯示文件,如何才能得到explorer使用的相同圖象?
A 可以將系統的ImageList加到LISTCTRL上,然後用具有SHGFI_ICON標誌的SHGetFileInfo獲取適當的圖標索引:
//圖象列表設置
HIMAGELIST himagelist;
SHFILEINFO fi;
CImageList m_smalllist;
//得到系統小圖標列表的句柄
himagelist = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C://"),0,&fi,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
//添加到小圖象列表
m_smalllist.Attach(himagelist);
//設置LISTCTRL的圖象列表
m_listCtrl.SetImageList(&m_smalllist,LVSIL_SMALL);
//分離圖象列表
m_smalllist.Detach();
//-------------------------------------------------
Q 如何在列表的任何一列顯示圖標,而不是第一列?
A
LV_ITEM item;
...
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
item.iItem = ...//設置行號
item.lParam = ...//如何需要就設置lparam參數
item.iSubItem = ...//設置列號,從0開始的
item.stateMask = LVIS_STATEIMAGEMASK;
item.state = INDEXTOSTATEIMAGEMASK(...);//參數爲圖標號
item.iImage = ...//設置圖標號
item.pszText = ...//顯示文本
//插入新項
m_listctrl.InsertItem(&item);
//現在設置圖標
m_listctrl.SetItemText(0,4,szField);
//-------------------------------------------------
Q 給LISTBOX添加新項時如何實現自動下滾?
A 在調用AddString後,添加如下代碼:
m_listbox.SetTopIndex(m_listbox.GetCount()-1);
//-------------------------------------------------
Q listBox的文本超過框的寬度時,如何讓水平滾動條正常工作?
A 用下面的代碼,設置滾動條的寬度爲最長的字符串寬度
void SetHorizontalExtent(CListBox &listbox)
{
int index = listbox.GetCount();
if(index == LB_ERROR)
return;
int nExtent = 0;
if(index)
{
CDC *pDC = listbox.GetDC();
CFont *poldfont = pDC->SelectObject(listbox.GetFont());
CString s;
SIZE text;
LONG maxtxt = 0;
whilw(index--)
{
listbox.GetText(index,s);
text = pDC->GetOutputTextExtent(s);
if(text.cx > maxtxt)
maxtxt = text.cx;
}
text.cx = maxtxt;
pDC->LPToDP(&text);
nExtent = text.cx+2;
pDC->SelectObject(poldfont);
listbox.ReleaseDC(pDC);
}
listbox.SetHorizontalExtent(nExtent);
}
//-------------------------------------------------
18.Q 在拆分視圖的時候,創建了四個視圖(2行2列),右下的是CFormView,其他的都是CView,在CMainFrame的OnCreateCilent不管怎麼指定CRect的大小,下方的兩個視圖都佔了整個窗口,需要拖動!
A 一般只需要在OnCreateClient的末尾添加:
m_wndSpitter.SetRowInfo(0,200,0);//添加此行代碼
//-------------------------------------------------
Q 如何指定拆分窗口的最小寬度?
A 使用CSpitterWnd::SetColumnInfo()
void SetColumnInfo(int col, //指定列
int deal, //理想寬度(像素)
int cxmin); //最小寬度(像素)
在使用SetColumnInfo之後還應該調用RecalLayout();重新調整佈局。
//--------------------------------------------------
Q 如何判斷工具欄是水平還是垂直的?
A if((m_toolbar.GetBarStyle() & CBRS_ALIGN_LEFT) == CBRS_ALIGN_LEFT ||
(m_toolbar.GetBarStyle() & CBRS_ALIGN_RIGHT) == CBRS_ALIGN_RIGHT)
AfxMessageBox("vertical");
else
AfxMessageBox("horizontal");
//--------------------------------------------------
Q 編程方式修改工具欄按鈕的可見性?
A 示例代碼:
DWORD style = m_toolbar.GetButtonStyle(nIndex);
if(m_bHide)
m_toolbar.SetButtonStyle(nIndex,style & ~WS_VISIBLE);
else
m_toolbar.SetButtonStyle(nIndex,style | WS_VISIBLE);
m_bHide = !m_bHide;
//--------------------------------------------------
Q 如何在狀態欄添加按鈕並響應?
A 創建一個從CButton派生的CMyButton類,在主框架類添加CMyButton類的成員變量,然後在OnCreate函數中創建按鈕,並把它和狀態欄關聯起來:
m_mybtn.Create("MyButton",WS_CHILD | VISIBLE,CRect(0,0,60,20),&m_WndStatusBar,0);
通過處理BN_CLICKED消息,可以在CMyButton類中處理所有的點擊事件
//--------------------------------------------------
Q 如何隱藏屬性CPropertySheet的標題欄,使用ModifyStyle(WINDOW_CAPTION,0)沒有效果
A 創建自己的CPropertySheet派生類,並覆蓋OnInitDialog,轉到默認的情況後,使用ModifyStyle來刪除WS_CAPTION標誌
//--------------------------------------------------
Q 如何讓屬性頁有兩行標籤?
A 從CPropertySheet派生類,添加PreCreateWindow的處理,在調用基類之前添加代碼:
cs.style |= TCS_MULTILINE;
//------------------------------------------------------
Q 如何在屬性表的兩個頁之間傳遞數據?
A
CPropertyPage有一個成員函數QuerySiblings(WPARAM, LPARAM)。應用程序可以使用這個函數。
QuerySiblings生成一條PSM_QUERYSIBLINGS消息,它傳遞給所有的兄弟,也就是屬性表上的其他屬性頁。 一般可創建一個所有頁可見的枚舉,如:
enum{QUERY_MY_STRING, QUERY_SOMETHING_ELSE,.......}
然後,在一個屬性頁需要其他屬性頁中的信息時,使用代碼:
CString myString;
if(lL == QuerySiblings(QUERY_MY_STRING,(LPARAM)&myString))
{
....//獲取字符串
}
提供字符串的頁處理PSM_QUERYSIBLINGS消息:
LRESULT CPageThatHasString::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
{
if(QUERY_MY_STRING == wParam)
{
*((CString *)lParam) = _T(“Test String“);
return 1L;
}
else
return 0L;
}
//----------------------------------------------------------
Q 如何讓屬性頁具有兩行標籤?
A
從CPropertySheet派生一個自己的類,添加一個PreCreateWindow的處理,然後在調用基類的處理前加如下代碼:cs.style |= TCS_MULTILINE;
//-----------------------------------------------------------
Q 如何隱藏屬性頁的標題欄?
A
從CPropertySheet派生一個自己的類,並覆蓋OnInitDialog,在轉到默認的情況以後,使用 ModifyStyle來刪除標題欄標誌WS_CAPTION。
ModifyStyle(WS_CAPTION,0);
//-------------------------------------------------------------------
Q 如何枚舉桌面項目?
A
1 得到指向IShellFolder接口的指針
2 得到指向IMalloc接口的指針
3 得到指向IEnumIDList接口的指針
4 提取枚舉中下一項目的PIDL
5 測定PIDL代表的標誌符的類型
6 處理該項目
7 釋放PIDL分配的內存
8 重複4到7步,知道所有的項目都枚舉完
9 釋放IShellFolder IMalloc IEnumIDList接口的指針
LPSHELLFOLDER lpshellfolder;
LPMALLOC lpmalloc;
LPENUMIDLIST lpidlist;
m_namecount = 0;
HRESULT hr = SHGetDestopFolder(&lpshellfolder);
if(hr == NOERROR)
{
hr = ::SHGetMalloc(&lpmalloc);
if(hr == NOERROR)
{
hr = lpshellfolder->EnumObject(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,&lpidlist);
if(hr == NOERROR)
ProcessFolder(lpshellfolder,lpmalloc,lpidlist);//custom deal function
lpmalloc->Release();
lpidlist->Release();
InValidate();
}
lpshellfolder->Release();
}
void ***::ProcessFolder(LPSHELLFOLDER lpshellfolder,LPMALLOC lpmalloc,LPENUMIDLIST lpidlist)
{
STRRET strret;
ULONG numfetch;
LPITEMIDLIST lpitemlist;
HRESULT hr = lpidlist->Next(1,&lpitemlist,&numfetch);
while(hr == NOERROR)
{
ULONG attributes = SFGAO_FOLDER;
lpshellfolder->GetAttributes(1,(const struct _ITEMIDLIST **)&lpitemlist,&attributes);
if(attributes & SFGAO_FOLDER)
{
hr = lpshellfolder->GetDiaplayNameOf(lpitemlist,SHGDN_NORMAL,&strret);
if(m_nameCount < 20)
m_names[m_namecount++] = strret.str;
}
lpmalloc->Free(lpitemlist);
hr = lpidlist->Next(1,&lpitemlist,&numfetch);
}
}
//-------------------------------------------------------------------
Q 如何創建桌面快捷方式?
A:
1 initialize com
2 create LShellLink Object
3 Use IShellLink interface to get the pointer about IPersistFile
4 Use IShellLink interface to initialize link
5 Use LPersistFile interface to save the link
6 Release all the com pointer
7 Com return to previous status
1
HRESULT hr = CoInitialize(NULL);
if(hr == S_OK)
{
...//Continue
}
2
IShellLink *pshelllink;
pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink);
3
IPersistFile *persistfile;
persistfile = pshelllink->QueryInterface(IID_IPersistFile,(void **)&persistfile);
4
pshelllink->SetPath("C://config.sys");
pshelllink->SetDescription("ShortCut to config.sys");
5
char path[MAX_PATH];
GetWindowsDirectory(path,MAX_PATH);
int len = strlen(path);
strcpy(&path[len],"//desktop//config.lik");
//change the char from ANSI to UNICODE
OLECHAR widepath[MAX_PATH];
MultiByteToWideChar(CP_ACP,0,path,-1,widepath,MAX_PATH);
persistfile->Save(widepath,TRUE);
6
pshelllink->Release();
psersistfile->Release();
7
CoUnInitialize();
有部分代碼有點錯誤,但修改容易
19.Q 在拆分視圖的時候,創建了四個視圖(2行2列),右下的是CFormView,其他的都是CView,在CMainFrame的OnCreateCilent不管怎麼指定CRect的大小,下方的兩個視圖都佔了整個窗口,需要拖動!
A 一般只需要在OnCreateClient的末尾添加:
m_wndSpitter.SetRowInfo(0,200,0);//添加此行代碼
//-------------------------------------------------
Q 如何指定拆分窗口的最小寬度?
A 使用CSpitterWnd::SetColumnInfo()
void SetColumnInfo(int col, //指定列
int deal, //理想寬度(像素)
int cxmin); //最小寬度(像素)
在使用SetColumnInfo之後還應該調用RecalLayout();重新調整佈局。
//--------------------------------------------------
Q 如何判斷工具欄是水平還是垂直的?
A if((m_toolbar.GetBarStyle() & CBRS_ALIGN_LEFT) == CBRS_ALIGN_LEFT ||
(m_toolbar.GetBarStyle() & CBRS_ALIGN_RIGHT) == CBRS_ALIGN_RIGHT)
AfxMessageBox("vertical");
else
AfxMessageBox("horizontal");
//--------------------------------------------------
Q 編程方式修改工具欄按鈕的可見性?
A 示例代碼:
DWORD style = m_toolbar.GetButtonStyle(nIndex);
if(m_bHide)
m_toolbar.SetButtonStyle(nIndex,style & ~WS_VISIBLE);
else
m_toolbar.SetButtonStyle(nIndex,style | WS_VISIBLE);
m_bHide = !m_bHide;
//--------------------------------------------------
Q 如何在狀態欄添加按鈕並響應?
A 創建一個從CButton派生的CMyButton類,在主框架類添加CMyButton類的成員變量,然後在OnCreate函數中創建按鈕,並把它和狀態欄關聯起來:
m_mybtn.Create("MyButton",WS_CHILD | VISIBLE,CRect(0,0,60,20),&m_WndStatusBar,0);
通過處理BN_CLICKED消息,可以在CMyButton類中處理所有的點擊事件
//--------------------------------------------------
Q 如何隱藏屬性CPropertySheet的標題欄,使用ModifyStyle(WINDOW_CAPTION,0)沒有效果
A 創建自己的CPropertySheet派生類,並覆蓋OnInitDialog,轉到默認的情況後,使用ModifyStyle來刪除WS_CAPTION標誌
//--------------------------------------------------
Q 如何讓屬性頁有兩行標籤?
A 從CPropertySheet派生類,添加PreCreateWindow的處理,在調用基類之前添加代碼:
cs.style |= TCS_MULTILINE;
//------------------------------------------------------
Q 如何在屬性表的兩個頁之間傳遞數據?
A
CPropertyPage有一個成員函數QuerySiblings(WPARAM, LPARAM)。應用程序可以使用這個函數。
QuerySiblings生成一條PSM_QUERYSIBLINGS消息,它傳遞給所有的兄弟,也就是屬性表上的其他屬性頁。 一般可創建一個所有頁可見的枚舉,如:
enum{QUERY_MY_STRING, QUERY_SOMETHING_ELSE,.......}
然後,在一個屬性頁需要其他屬性頁中的信息時,使用代碼:
CString myString;
if(lL == QuerySiblings(QUERY_MY_STRING,(LPARAM)&myString))
{
....//獲取字符串
}
提供字符串的頁處理PSM_QUERYSIBLINGS消息:
LRESULT CPageThatHasString::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
{
if(QUERY_MY_STRING == wParam)
{
*((CString *)lParam) = _T(“Test String“);
return 1L;
}
else
return 0L;
}
//----------------------------------------------------------
Q 如何讓屬性頁具有兩行標籤?
A
從CPropertySheet派生一個自己的類,添加一個PreCreateWindow的處理,然後在調用基類的處理前加如下代碼:cs.style |= TCS_MULTILINE;
//-----------------------------------------------------------
Q 如何隱藏屬性頁的標題欄?
A
從CPropertySheet派生一個自己的類,並覆蓋OnInitDialog,在轉到默認的情況以後,使用 ModifyStyle來刪除標題欄標誌WS_CAPTION。
ModifyStyle(WS_CAPTION,0);
//-------------------------------------------------------------------
Q 如何枚舉桌面項目?
A
1 得到指向IShellFolder接口的指針
2 得到指向IMalloc接口的指針
3 得到指向IEnumIDList接口的指針
4 提取枚舉中下一項目的PIDL
5 測定PIDL代表的標誌符的類型
6 處理該項目
7 釋放PIDL分配的內存
8 重複4到7步,知道所有的項目都枚舉完
9 釋放IShellFolder IMalloc IEnumIDList接口的指針
LPSHELLFOLDER lpshellfolder;
LPMALLOC lpmalloc;
LPENUMIDLIST lpidlist;
m_namecount = 0;
HRESULT hr = SHGetDestopFolder(&lpshellfolder);
if(hr == NOERROR)
{
hr = ::SHGetMalloc(&lpmalloc);
if(hr == NOERROR)
{
hr = lpshellfolder->EnumObject(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,&lpidlist);
if(hr == NOERROR)
ProcessFolder(lpshellfolder,lpmalloc,lpidlist);//custom deal function
lpmalloc->Release();
lpidlist->Release();
InValidate();
}
lpshellfolder->Release();
}
void ***::ProcessFolder(LPSHELLFOLDER lpshellfolder,LPMALLOC lpmalloc,LPENUMIDLIST lpidlist)
{
STRRET strret;
ULONG numfetch;
LPITEMIDLIST lpitemlist;
HRESULT hr = lpidlist->Next(1,&lpitemlist,&numfetch);
while(hr == NOERROR)
{
ULONG attributes = SFGAO_FOLDER;
lpshellfolder->GetAttributes(1,(const struct _ITEMIDLIST **)&lpitemlist,&attributes);
if(attributes & SFGAO_FOLDER)
{
hr = lpshellfolder->GetDiaplayNameOf(lpitemlist,SHGDN_NORMAL,&strret);
if(m_nameCount < 20)
m_names[m_namecount++] = strret.str;
}
lpmalloc->Free(lpitemlist);
hr = lpidlist->Next(1,&lpitemlist,&numfetch);
}
}
//-------------------------------------------------------------------
Q 如何創建桌面快捷方式?
A:
1 initialize com
2 create LShellLink Object
3 Use IShellLink interface to get the pointer about IPersistFile
4 Use IShellLink interface to initialize link
5 Use LPersistFile interface to save the link
6 Release all the com pointer
7 Com return to previous status
1
HRESULT hr = CoInitialize(NULL);
if(hr == S_OK)
{
...//Continue
}
2
IShellLink *pshelllink;
pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink);
3
IPersistFile *persistfile;
persistfile = pshelllink->QueryInterface(IID_IPersistFile,(void **)&persistfile);
4
pshelllink->SetPath("C://config.sys");
pshelllink->SetDescription("ShortCut to config.sys");
5
char path[MAX_PATH];
GetWindowsDirectory(path,MAX_PATH);
int len = strlen(path);
strcpy(&path[len],"//desktop//config.lik");
//change the char from ANSI to UNICODE
OLECHAR widepath[MAX_PATH];
MultiByteToWideChar(CP_ACP,0,path,-1,widepath,MAX_PATH);
persistfile->Save(widepath,TRUE);
6
pshelllink->Release();
psersistfile->Release();
7
CoUnInitialize();
有部分代碼有點錯誤,但修改容易
20.一、新建一個類,已經保存,爲何有時候在"ClassView"裏看不到這個類?
答:菜單[工程]->[添加到工程...]->[文件...]添加XXXClass.h和.cpp文件,如果在"ClassView"裏還是看不到,"FileView"裏找到XXXClass.h文件,在class CXXXClass的CXXXClass這個地方任意改變類名,此時就看到了,之後再改變爲CXXXClass.
二、怎麼改變對話框上各控件的tab順序?
答:在資源視圖,對話框IDD_DIALOG1下,按Ctrl+D,看到各個控件前有個數字,這個數字便是TAB鍵順序,按照你要求重新排序這些數字便可。
三、在使用COMBOBOX時,怎麼設置當彈出下拉列表框時的高度?
答:在資源視圖,找到IDC_COMBOBOX1,單擊“箭頭”,此時調整個高度便是下拉列表框可見時的高度,如果是動態create出來的,參數rect的高便是下拉列表框可見時的高,而CComboBox::SetItemHeight(-1, 15)爲設置組合框高度。
四、在IDC_LIST1與CListCtrl m_list關聯後,有時輸入m_list.後並沒有智能提示出CListCtrl的函數是怎麼回事?
答:是VC開發環境的BUG,我個人的解決方法是先用CXXXClass::出現提示後定位選擇函數,再把CXXXClass::換成變量名.這個問題希望有朋友可以解答下。
五、在用TabCtrl控件時,爲何不可以按標籤頁來定製某頁上的控件?
答:VC的TabCtrl不支持這樣的操作,方法是先建立一對話框資源IDD_DIALOGX(跟工程無關的),把某標籤頁上所有控件調整大小並排版,然後全選粘貼在工程中正式的對話框IDD_DIALOG1中,反覆這樣的操作,tabctrl有幾頁就招待幾次,最後再添加TabCtrl在IDD_DIALOG1中,然後通過將IDC_TABCTRL1與CTabCtrl m_tab1關聯,之後添加IDC_TABCTRL1的TCN_SELCHANGE消息處理函數,便可用int nPage = m_tab1.GetCurSel()取得當前標籤號,接着再用switch(nPage)來選擇處理各頁顯示的控件,控件顯示可用ShowWindow(SW_SHOW/SW_HIDE)來控制,小技巧,在第一步時,可有意識的將第某頁上的控件ID設爲IDC_TAB1_NAME,IDC_TAB2_NAME,這樣的形式,便於清楚的知道哪個控件是第幾頁中的。
在debug窗口怎麼看不到調試輸出的信息?
用Go不要用Run來運行。