VC关闭重定向Wow64DisableWow64FsRedirection需要xcode 导入头文件什么头文件

今天看啥 热点:
写一个Windows上的守护进程(5)文件系统重定向,守护进程重定向写一个Windows上的守护进程(5)文件系统重定向
在Windows上经常操作文件或注册表的同学可能知道,有&文件系统/注册表重定向&这么一回事。大致来说就是32位程序在64位的Windows上运行时,操作系统会把对System32文件夹的访问重定向到SysWow64下,把对HKEY_LOCAL_MACHINE\SOFTWARE的访问重定向到HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node下。当然不止这些路径和注册表。详情请查看MSDN:https://msdn.microsoft.com/en-us/library/aa384187.aspx 和https://msdn.microsoft.com/en-us/library/aa384232(v=vs.85).aspx 。
我们通常为了方便发布,都只会编译一份32位的程序,不会编译64的程序。如果代码中涉及到了访问文件和注册表,那就要考虑这个问题了。
Windows提供了两个API(准确的说是3个,但其中一个已不推荐使用了)来禁用文件系统/注册表重定向:Wow64DisableWow64FsRedirection,Wow64RevertWow64FsRedirection。顾名思义,前者用于禁用,后者用于恢复。
有的同学可能就说了:我一直禁用就行了,干嘛还要恢复?这你就想少了,有的代码段可能并不关心是否有重定向,所以并没有考虑这个问题,假若这个代码段的结果会影响多个线程,而你刚好又把包含这个代码段的某一线程的重定向禁用了,那就成了有的线程禁用了重定向,有的线程没有禁用,获取的结果就不一致了。
一般我们在会有重定向问题的函数调用前禁用重定向,调用完毕后,恢复重定向。这很容易让人想到使用RAII手法:在类构造函数中禁用,析构函数中恢复:
class scoped_disable_wow64_fsredirection : public boost::noncopyable
scoped_disable_wow64_fsredirection();
~scoped_disable_wow64_fsredirection();
static bool disable(void **ppOldValue);
static bool revert(void *pOldValue);
void *_pOldV
构造函数的实现中调用了disable,析构函数的实现中调用了revert。
其中disable就是调用了Wow64DisableWow64FsRedirection,revert就是调用了Wow64RevertWow64FsRedirection。
注:类名字这么长是为了能够达到&顾名思义&的程度。还没想到什么更好的名字。哎,起名真是个头疼的事。
但是我们不能直接调用这两个Windows API,为什么呢?
static boost::once_flag once_;
typedef int (__stdcall *fnWow64DisableWow64FsRedirection)(void *);
typedef int (__stdcall *fnWow64RevertWow64FsRedirection)(void *);
static fnWow64DisableWow64FsRedirection g_fnWow64DisableWow64FsRedirection = NULL;
static fnWow64RevertWow64FsRedirection g_fnWow64RevertWow64FsRedirection = NULL;
static void load_wow64_funcs()
g_fnWow64DisableWow64FsRedirection = reinterpret_cast&fnWow64DisableWow64FsRedirection&
(WindowsUtil::load_function("Kernel32.dll", "Wow64DisableWow64FsRedirection"));
g_fnWow64RevertWow64FsRedirection = reinterpret_cast&fnWow64RevertWow64FsRedirection&
(WindowsUtil::load_function("Kernel32.dll", "Wow64RevertWow64FsRedirection"));
scoped_disable_wow64_fsredirection::scoped_disable_wow64_fsredirection()
: _pOldValue(NULL)
boost::call_once(once_, load_wow64_funcs);
disable(&_pOldValue);
scoped_disable_wow64_fsredirection::~scoped_disable_wow64_fsredirection()
revert(_pOldValue);
bool scoped_disable_wow64_fsredirection::disable(void **ppOldValue)
bool ret = true;
if (g_fnWow64DisableWow64FsRedirection)
if (!g_fnWow64DisableWow64FsRedirection(ppOldValue))
ErrorLogLastErr("Wow64DisableWow64FsRedirection fail");
ret = false;
bool scoped_disable_wow64_fsredirection::revert(void *pOldValue)
bool ret = true;
if (g_fnWow64RevertWow64FsRedirection)
if (!g_fnWow64RevertWow64FsRedirection(pOldValue))
ErrorLogLastErr("Wow64RevertWow64FsRedirection fail");
ret = false;
这里用了前面文章讲到的call_once去加载这两个函数。
load_function封装了GetModuleHandleA- GetProcAddress两个函数的调用,详情请参看源码。
使用时,仅需定义一个类实例就可以了。切记,要尽量缩小作用域,以免影响其他代码段。
源码:https://git.oschina.net/mkdym/DaemonSvc.git (主)&& https://github.com/mkdym/DaemonSvc.git (提升逼格用的)。
暂无相关文章
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&
C++教程最近更新您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
VC命令行编译C++..doc 20页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:150 &&
VC命令行编译C
你可能关注的文档:
··········
··········
编译器 cl.exe
连接器 mlink.exe
编译格式:
[option...] file... [option | file]... [lib...] [@command-file] [/link link-opt...]
option是编译参数
file是编译的源文件
lib是程序需要的依赖库
command-file是命令行文件
当命令行参数过长,CMD不支持时,可将一部分命令移到文件中,附加该文件使得文件中的命令有效
link-opt 是链接选项,在输入/link后输入链接选项,则可以把这些选项传递给链接器。
注意:在格式中[option] file [option] file 虽然是options是分开了,但是所有的options都是同时作用于所有file的。
例如 cl /MT main.cpp /LD submain.cpp 的意思是 /MT /LD同时对这个两个文件起作用。相同的/互斥的参数,以后出现的为准。
例如 cl /Fo”src\\” main.cpp /Fo”symbol\\” submain.cpp 生成的obj文件都会放在symbol文件夹下。
下面介绍编译器(cl)的参数(options)
有些参数后面标记过期,该参数在VS2005下仍然有效,但是在后续版本中可能会被删除。在VS2005中可能会有其他参数来代替过期参数,在各个过期参数中会有说明。
优化选项:
体积最小优化 相当于/Og /Os /Oy /Ob2 /Gs /GF /Gy的组合
速度最快优化 相当于/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy的组合
扩展inline函数。
/Ob0 禁用内联。默认值。
/Ob1 仅仅内联被标识为 inline,__inline __forceinline,在class定义中写函数实现
例如class CTest
int GetInt()
return m_iI
该函数在/Ob1的参数下,会被编译成内联函数。
/Ob2 包含/Ob1的情况,并且编译器会把可以编译成内联,但是没有加上inline关
键字的函数内联。
省略帧指针。该参数被/O1 /O2 /Ox包含,如果需要使用帧指针,可以在后面加上/Oy-,即可使/Oy失效,该参数仅在x86下有效。
禁用Debug,加快编译速度,简化调试功能。
全局优化 包括表达式省略和循环优化。
表达式省略:
在该优化下,b+c的值只计算一次存入临时变量。
循环优化:
while(i&0)
在该优化下,x + y的值会先计算出来,等效于:
while(i&0)
用函数体替换函数调用。编译器会将内建函数的函数体替换掉函数调用语句,这样
可以避免函数调用时的开销提高运行速度,但是扩大了代码长度。只有内建的函数
才能被替换。库函数中的内建函数如下:
strcmp _enable _outpw labs strcpy _inp _rotl
strlen _inpw _rotr
memcpy _lrotl _strset memset _lrotr
abs strcat
内建函数不存在于库中,而存在于编译器中。
代码长度优化
运行速度优化
以上两个优化只能取一种
int differ(int x)
return x * 71;
如果选择/Os 代码长度优化,则编译为
eax, DWORD PTR _x$[ebp]
;长度很短,但是该计算比较慢
如果选择/Ot 运行速度优化,则编译为
eax, DWORD PTR _x$[ebp]
eax, DWORD PTR [eax+ea
正在加载中,请稍后...VC编程常见问题
编辑:www.fx114.net
本篇文章主要介绍了"VC编程常见问题",主要涉及到VC编程常见问题方面的内容,对于VC编程常见问题感兴趣的同学可以参考一下。
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& & & & & & & & &
& & UINT uID;& & & & & & & &
& & UINT uCallbackM& & &
& & DWORD Reserved[2];& & & & &
& & HICON hI& & & & & & & & //托盘图标的句柄
要获取到这个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&
HINSTANCE&
typedef& &
int& & & &
(__stdcall&
Wow64DisableWow64FsRedirection)(LPVOID);
YWow64DisableWow64FsRedirection&
f_Wow64DisableWow64FsRedirection&
typedef& &
int& & & &
(__stdcall&
Wow64RevertWow64FsRedirection)(LPVOID);
Wow64RevertWow64FsRedirection&
f_Wow64RevertWow64FsRedirection&
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,&
"http://www.csdn.net",&
NULL,NULL,SW_SHOWMAXIMIZED);
这样可以打开一个网页,但不是在新IE中打开,改成下面方式时就可以在一个新的IE中打开网页了
ShellExecute(NULL,&
"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 wpOrigEditP
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);
if(GetKeyState(VK_CONTROL) & 0x8000)
& & return CallWindowProc(wpOrigEditProc,hDlg,uiMsg,wParam,lParam);
return CallWindowProc(wpOrigEditProc,hDlg,uiMsg,wParam,lParam);
//一些帮助函数 //返回当前程序的路径 //例如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 hT if(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { LUID uID; ::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &uID); TOKEN_PRIVILEGES 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_ va_start(args, lpszFormat); int nB TCHAR szBuffer[512]; nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args); OutputDebugString(szBuffer); va_end(args); #endif } //从地址去获得模块基址 HMODULE WINAPI ModuleFromAddress(PVOID pv) { MEMORY_BASIC_INFORMATION if(::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) { return (HMODULE)mbi.AllocationB } 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_ va_start(args, lpszFormat); int nB TCHAR szBuffer[1024]; nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args); str = szB va_end(args); } //提升所需的权限 BOOL EnablePrivilege(LPCTSTR lpName,BOOL bEnable) { BOOL bOk = FALSE; HANDLE hT if(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { LUID uID; ::LookupPrivilegeValue(NULL, lpName, &uID); TOKEN_PRIVILEGES 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; } 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); } } ////////////////////////////////////////////////////////////////////////// //显示文件属性 void ShowProperties(string strPath) { SHELLEXECUTEINFO 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,"+strP ShellExecute(NULL,NULL,"explorer",cmd.c_str(),NULL,SW_SHO
1.动态修改ComboBox的DROPDOWN,DROPDOWNLIST属性
=& ::GetWindow( GetDlgItem(IDC_COMBO1)-&m_hWnd& ,&
theStyle = GetWindowLong(GetDlgItem(IDC_COMBO1)-&m_hWnd, GWL_STYLE&
~CBS_DROPDOWN;//去掉DROPDOWN&
CBS_DROPDOWNLIST; //添加DROPDOWNLIST
::DestroyWindow(&
SetWindowLong(GetDlgItem(IDC_COMBO1)-&m_hWnd, GWL_STYLE&
2.从txt文件中一行一行地读数据
建议使用CFile和CArchive结合,利用CArchive的ReadString函数进行逐行读取。
file.Open("d://temp//myfile.txt",CFile::modeRead | CFile::shareDenyWrite);
CArchive arf(&file,CArchive::load);
CString strT
arf.ReadString(strTemp);
arf.Close();
file.Close();
如何制作透明窗体
  使用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");
 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的话就完全透明,看不到了。
如何使框架窗口的图标为动画显示
  可以用TIMER,但是TIMER不能有效的定时。因为TIMER发送的是窗口消息,当窗口忙于处理键盘、鼠标等消息时就不能及时处理TIMER,会使间隔时间变得很长 。
  可以考虑用一个单独得TIMER线程,用Sleep()定时来解决此问题。
UINT Timer(LPVOID param)
 HWND hWnd=(HWND)
 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;
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 *
CWnd *pWnd = pcombo-&GetWindow(GW_CHILD);
while(pWnd)
& char classname[256];
& ::GetClassName(pWnd-&m_hWnd,classname,256)
& if(strcmp(classname,"edit") == 0)
pEdit = new CEdit();
pEdit-&SubClassWindow(pWnd-&m_hWnd);
pEdit-&SetReadOnly();
pWnd = pWnd-&GetNextWindow();
& 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);
//其中m_edit是CEdit类的实现,它在WM_RBUTTONUP上显示右键菜单
//-------------------------------------------------
Q 如何给按钮加位图
对动态创建的按钮:
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 如何设置编辑控件的数字限制属性?
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
SHFILEINFO
CImageList m_
//得到系统小图标列表的句柄
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 如何在列表的任何一列显示图标,而不是第一列?
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)
& & int nExtent = 0;
& & if(index)
& & & & CDC *pDC = listbox.GetDC();
CFont *poldfont = pDC-&SelectObject(listbox.GetFont());
LONG maxtxt = 0;
whilw(index--)
& & & & & &
listbox.GetText(index,s);
& & & text = pDC-&GetOutputTextExtent(s);
& & & if(text.cx & maxtxt)
& & & & & & & &
maxtxt = text.
& & & & text.cx =
& & & pDC-&LPToDP(&text);
& & & nExtent = text.cx+2;
& & & pDC-&SelectObject(poldfont);
& & & listbox.ReleaseDC(pDC);
& & listbox.SetHorizontalExtent(nExtent);
//-------------------------------------------------
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");
AfxMessageBox("horizontal");
//--------------------------------------------------
Q 编程方式修改工具栏按钮的可见性?
A 示例代码:
DWORD style = m_toolbar.GetButtonStyle(nIndex);
if(m_bHide)
m_toolbar.SetButtonStyle(nIndex,style & ~WS_VISIBLE);
m_toolbar.SetButtonStyle(nIndex,style | WS_VISIBLE);
m_bHide = !m_bH
//--------------------------------------------------
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 如何在属性表的两个页之间传递数据?
CPropertyPage有一个成员函数QuerySiblings(WPARAM, LPARAM)。应用程序可以使用这个函数。
QuerySiblings生成一条PSM_QUERYSIBLINGS消息,它传递给所有的兄弟,也就是属性表上的其他属性页。&
一般可创建一个所有页可见的枚举,如:
enum{QUERY_MY_STRING,& QUERY_SOMETHING_ELSE,.......}
然后,在一个属性页需要其他属性页中的信息时,使用代码:
CString myS
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;
& & & & & & & return 0L;
//----------------------------------------------------------
Q& 如何让属性页具有两行标签?
从CPropertySheet派生一个自己的类,添加一个PreCreateWindow的处理,然后在调用基类的处理前加如下代码:cs.style |= TCS_MULTILINE;
//-----------------------------------------------------------
Q& 如何隐藏属性页的标题栏?
从CPropertySheet派生一个自己的类,并覆盖OnInitDialog,在转到默认的情况以后,使用 ModifyStyle来删除标题栏标志WS_CAPTION。
ModifyStyle(WS_CAPTION,0);
//-------------------------------------------------------------------
Q 如何枚举桌面项目?
1 得到指向IShellFolder接口的指针
2 得到指向IMalloc接口的指针
3 得到指向IEnumIDList接口的指针
4 提取枚举中下一项目的PIDL
5 测定PIDL代表的标志符的类型
6 处理该项目
7 释放PIDL分配的内存
8 重复4到7步,知道所有的项目都枚举完
9 释放IShellFolder IMalloc IEnumIDList接口的指针
LPSHELLFOLDER
LPENUMIDLIST
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)
LPITEMIDLIST
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
& & & & & & &
m_names[m_namecount++] = strret.
lpmalloc-&Free(lpitemlist);
hr = lpidlist-&Next(1,&lpitemlist,&numfetch);
//-------------------------------------------------------------------
Q& 如何创建桌面快捷方式?
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
HRESULT hr = CoInitialize(NULL);
if(hr == S_OK)
& ...//Continue
IShellLink *
pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink);
IPersistFile *
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();
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");
AfxMessageBox("horizontal");
//--------------------------------------------------
Q 编程方式修改工具栏按钮的可见性?
A 示例代码:
DWORD style = m_toolbar.GetButtonStyle(nIndex);
if(m_bHide)
m_toolbar.SetButtonStyle(nIndex,style & ~WS_VISIBLE);
m_toolbar.SetButtonStyle(nIndex,style | WS_VISIBLE);
m_bHide = !m_bH
//--------------------------------------------------
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 如何在属性表的两个页之间传递数据?
CPropertyPage有一个成员函数QuerySiblings(WPARAM, LPARAM)。应用程序可以使用这个函数。
QuerySiblings生成一条PSM_QUERYSIBLINGS消息,它传递给所有的兄弟,也就是属性表上的其他属性页。&
一般可创建一个所有页可见的枚举,如:
enum{QUERY_MY_STRING,& QUERY_SOMETHING_ELSE,.......}
然后,在一个属性页需要其他属性页中的信息时,使用代码:
CString myS
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;
& & & & & & & return 0L;
//----------------------------------------------------------
Q& 如何让属性页具有两行标签?
从CPropertySheet派生一个自己的类,添加一个PreCreateWindow的处理,然后在调用基类的处理前加如下代码:cs.style |= TCS_MULTILINE;
//-----------------------------------------------------------
Q& 如何隐藏属性页的标题栏?
从CPropertySheet派生一个自己的类,并覆盖OnInitDialog,在转到默认的情况以后,使用 ModifyStyle来删除标题栏标志WS_CAPTION。
ModifyStyle(WS_CAPTION,0);
//-------------------------------------------------------------------
Q 如何枚举桌面项目?
1 得到指向IShellFolder接口的指针
2 得到指向IMalloc接口的指针
3 得到指向IEnumIDList接口的指针
4 提取枚举中下一项目的PIDL
5 测定PIDL代表的标志符的类型
6 处理该项目
7 释放PIDL分配的内存
8 重复4到7步,知道所有的项目都枚举完
9 释放IShellFolder IMalloc IEnumIDList接口的指针
LPSHELLFOLDER
LPENUMIDLIST
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)
LPITEMIDLIST
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
& & & & & & &
m_names[m_namecount++] = strret.
lpmalloc-&Free(lpitemlist);
hr = lpidlist-&Next(1,&lpitemlist,&numfetch);
//-------------------------------------------------------------------
Q& 如何创建桌面快捷方式?
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
HRESULT hr = CoInitialize(NULL);
if(hr == S_OK)
& ...//Continue
IShellLink *
pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink);
IPersistFile *
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();
一、新建一个类,已经保存,为何有时候在"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,这样的形式,便于清楚的知道哪个控件是第几页中的。
1. 窗口最大化、最小化的实现
当我们不能用标题栏的最大化、最小化及恢复按钮而又需在其他的地方实现这些功能,可以在指定的消息处理函数里添加:
WINDOWPLACEMENT
WINDOWPLACEMENT *
pwndpl = &
GetWindowPlacement(pwndpl);
pwndpl-&showCmd = SW_SHOWMINMIZED; //实现窗口最小化
SetWindowPlacement(pwndpl);
其中GetWindowPlacement()函数获取当前窗口布局的结构WINDOWPLACEMENT的结构变量指针,结构WINDOWPLACEMENT定义为:
typedef struct tagWINDOWPLACEMENT{
& & UINT showC
& & POINT ptMinP
& & POINT ptMaxP
& & RECT rcNormalP
}WINDOWPLACEMENT;
其中的成员变量showCmd确定当前窗口的状态,取值一般为:
&SW_HIDE:隐藏窗口
&SW_MINIMIZE:最小化指定的窗口
&SW_RESTORE:恢复原来的大小
&SW_SHOW:以原来的大小激活并显示
&SW_SHOWMAXIMIZED:激活并最大化窗口
SetWindowPlacement()函数就是按WINDOWPLACEMENT的设置来显示窗口
2. 为什么要使用GetSafeHwnd()函数
当我们想得到一个窗口对象(CWnd的派生对象)指针的句柄(HWND)时,最安全的方法是使用GetSafeHwnd()函数,通过下面的例子来看其理由:
CWnd *pwnd = FindWindow(&ExploreWClass&,NULL); //希望找到资源管理器
HWND hwnd = pwnd-&m_ //得到它的HWND
这样的代码当开始得到的pwnd为空的时候就会出现一个&General protection error&,并关闭应用程序,因为一般不能对一个NULL指针访问其成员,如果用下面的代码:
CWnd *pwnd = FindWindow(&ExploreWClass&,NULL); //希望找到资源管理器
HWND hwnd = pwnd-&GetSafeHwnd(); //得到它的HWND
就不会出现问题,因为尽管当pwnd是NULL时,GetSafeHwnd仍然可以用,只是返回NULL,通过GetSafeHwnd()的实现代码就更清楚了:
_AFXWIN_INLINE HWND CWnd::GetSafeHwnd() const
return this == NULL?NULL:m_hW
3. 如何使程序处于极小状态
如果我们不想让程序的窗口被别人看见,就可以让它保持在极小状态:在恢复程序窗口的时候,Window会发送WM_QUERYOPEN消息,只要在其消息处理函数里返回false就可以了。
BOOL CmainFrame::OnQueryOpen()
4. 如何禁止和能用关闭按钮
Cmenu *pmenu = AfxGetMainWnd()-&GetSystemMenu(FALSE);
pmenu-&EnableMenuItem(SC_CLOSE,MF_BYCOMMAND|MF_GRAYED);
恢复时只需将MF_GRAYED改为MF_ENABLED
5. 如何在程序中延时
使用sleep函数,如延时2秒,用sleep(2000);
使用sleep函数的不利在于延时期间不能处理其他的消息,如果时间太长,就好象死机一样,利用ColeDateTime类和ColeDateTimeSpan类实现延时就不会出现那样的问题:
ColeDateTime start_time = ColeDateTime::GetCurrentTime();
ColeDateTimeSpan end_time = ColeDateTime::GetCurrentTime()-start_
While(end_time.GetTotalSeconds()
GetMessage(&msg,NULL,0,0);
PreTranslateMessage(&msg);
End_time = ColeDateTime::GetCurrentTime-start_
这样在延时的时候我们也能够处理其他的消息。
看了论坛里的一些总结文章很好,我把里面没有怎么看到的也写了一点点出来,不知道有没有重复,希望能有些微的作用.
本文引用通告地址: http://blog.csdn.net/laiyiling/services/trackbacks/22293.aspx
6. 如何创建可伸缩的对话框
在进行对话框的设计时,有时候我们需要设计可伸缩的对话框,当用户按下某个按钮时弹出或隐藏对话框的下半部分。
(1)、首先在对话框中建立一个图片控件把ID设为IDC_DIVIDER,Type设置为矩形,Color设置为黑色,并将其设定为一线状,拖放在适当的位置做为伸缩对话框的分割线,属性设为不可见。
(2)、实现的原理:先获取对话框的尺寸大小,然后根据的位置来确定缩减后的对话框大小,其实对话框伸缩的变化就是的值,在缩减对话框后,我们要使不可见的部分控件被禁止,以禁止加速键和TAB键对其的操作,在扩展对话框后,原来被禁止的控件又要使能。
先在对话框上的伸缩按钮添加单击消息处理函数:
void C***Dlg::OnButtonExpand()
static int bexpand = FALSE; //设初始时为已扩展的
ExpandDialog(IDC_DIVIDER,bexpand);//调用扩展或缩减处理函数
Bexpand = !//状态取反,为下次的单击处理准备
//在对话框中添加一个成员函数ExpandDialog,用于扩展或缩减
void C***Dlg::ExpandDialog(int nResourceID,BOOL bexpand)
//参数nResourceID表示分割线的ID
//参数bexpand为TRUE时表示要扩展对话框,否则缩减对话框
static CRect rcL
static CRect rcS
if(rcLarge.IsRectNULL()) //首次使用时记下对话框的最大、最小尺寸
CWnd *pwndLand = GetDlgItem(nResourceID);
ASSERT(pwndLand);
GetWindowRect(rcLarge);
pwndLand-&GetWindowRect(rcLandmark);
rcSmall = rcL
rcSmall.bottom = rcLandmark.
if(bexpand)
SetWindowPos(NULL,0,0,rcLarge.Width(),rcLarge.Height(),
SWP_NOMOVE|SWP_NOZORDER);
EnableVisible();
SetWindowPos(NULL,0,0,rcSmall.Width(),rcSmall.Height(),
SWP_NOMOVE|SWP_NOZORDER);
EnableVisible();
//在对话框中添加一个成员函数EnableVisible,用于能用和禁止部分控件
void C***Dlg:: EnableVisible()
CWnd *pwnd = GetDlgItem(GW_CHILD);
GetWindowRect(rcShow);
While(pwnd != NULL)
pwnd-&GetWindowRect(rcControl);
if(rcTest.IntersectRect(rcShow,rcControl))
pwnd-&EnableWindow(TRUE);
pwnd-&EnableWindow(FALSE);
pwnd = pwnd-&GetWindow(GW_HWNDNEXT);
7. 为什么有RichEdit控件的对话框无法显示
如果在对话框上放一个RichEdit控件,往往发现对话框却无法正常显示,这是因为应用程序还没有为RichEdit控件的编辑功能做好准备,解决办法
就是在应用程序的InitInstance()函数调用AfxInitRichEdit()函数初始化RichEdit控件
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:}

我要回帖

更多关于 xcode 自动导入头文件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信