虽然有些内容不够规范不够严谨,但是可以在大家遇到问题时提供一些思路和方向:
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索引到这个图标句柄了 //释放内存代码略
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);
ShellExecute(NULL, "open", "http://www.csdn.net", NULL,NULL,SW_SHOWMAXIMIZED);这样可以打开一个网页,但不是在新IE中打开,改成下面方式时就可以在一个新的IE中打开网页了
ShellExecute(NULL, "open", "IEXPLORE", "http://www.csdn.net",NULL,SW_SHOWMAXIMIZED);
PurgeComm(hCom,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
ShellExecute(GetDesktopWindow()->m_hWnd,"open","control.exe","desk.cpl Display,@Theme","",SW_SHOW );
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.
例子代码::在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) } }
17、常见Q&A
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); }
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(); }
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上显示右键菜单
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)));
long Style = GetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE); Style |= ES_NUMBER; SetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE,Style);
//图象列表设置 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();
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);
m_listbox.SetTopIndex(m_listbox.GetCount()-1);
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&A(二)
Q 在拆分视图的时候,创建了四个视图(2行2列),右下的是CFormView,其他的都是CView,在CMainFrame的OnCreateCilent不管怎么指定CRect的大小,下方的两个视图都占了整个窗口,需要拖动!
A 一般只需要在OnCreateClient的末尾添加:
m_wndSpitter.SetRowInfo(0,200,0);//添加此行代码
void SetColumnInfo(int col, //指定列 int deal, //理想宽度(像素) int cxmin); //最小宽度(像素)在使用SetColumnInfo之后还应该调用RecalLayout();重新调整布局。
if((m_toolbar.GetBarStyle() & CBRS_ALIGN_LEFT) == CBRS_ALIGN_LEFT || (m_toolbar.GetBarStyle() & CBRS_ALIGN_RIGHT) == CBRS_ALIGN_RIGHT) AfxMessageBox("vertical"); else AfxMessageBox("horizontal");
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;
m_mybtn.Create("MyButton",WS_CHILD | VISIBLE,CRect(0,0,60,20),&m_WndStatusBar,0);通过处理BN_CLICKED消息,可以在CMyButton类中处理所有的点击事件
cs.style |= TCS_MULTILINE;
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; }
A 从CPropertySheet派生一个自己的类,添加一个PreCreateWindow的处理,然后在调用基类的处理前加如下代码:
cs.style |= TCS_MULTILINE;
ModifyStyle(WS_CAPTION,0);
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); } }
HRESULT hr = CoInitialize(NULL); if(hr == S_OK) { ...//Continue } IShellLink *pshelllink; pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink); IPersistFile *persistfile; persistfile = pshelllink->QueryInterface(IID_IPersistFile,(void **)&persistfile); pshelllink->SetPath("C://config.sys"); pshelllink->SetDescription("ShortCut to config.sys"); 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); pshelllink->Release(); psersistfile->Release(); CoUnInitialize();
有部分代码有点错误,但修改容易
19、常见问题记录
(1) 新建一个类,已经保存,为何有时候在"ClassView"里看不到这个类?
答:菜单[工程]->[添加到工程...]->[文件...]添加XXXClass.h和.cpp文件,如果在"ClassView"里还是看不到,"FileView"里找到XXXClass.h文件,在class CXXXClass的CXXXClass这个地方任意改变类名,此时就看到了,之后再改变为CXXXClass.
(2) 怎么改变对话框上各控件的tab顺序?
答:在资源视图,对话框IDD_DIALOG1下,按Ctrl+D,看到各个控件前有个数字,这个数字便是TAB键顺序,按照你要求重新排序这些数字便可。
(3) 在使用COMBOBOX时,怎么设置当弹出下拉列表框时的高度?
答:在资源视图,找到IDC_COMBOBOX1,单击“箭头”,此时调整个高度便是下拉列表框可见时的高度,如果是动态create出来的,参数rect的高便是下拉列表框可见时的高,而CComboBox::SetItemHeight(-1, 15)为设置组合框高度。
(4) 在IDC_LIST1与CListCtrl m_list关联后,有时输入m_list.后并没有智能提示出CListCtrl的函数是怎么回事?
答:是VC开发环境的BUG,我个人的解决方法是先用CXXXClass::出现提示后定位选择函数,再把CXXXClass::换成变量名.这个问题希望有朋友可以解答下。
(5) 在用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,这样的形式,便于清楚的知道哪个控件是第几页中的。