好久没有更新博客,也好久没看书了,忙了好一阵。偶尔闲下来的时候都去打游戏或者看电视。有一天走在校园里突然感觉自己开始颓废了。这是一个不好的征兆。正好一个项目快要结束,在项目中用到了一个方法,在Code Review的时候列出来,做一个总结。
一、在Vista操作系统中提升权限。
寻找在Vista下提成权限的方法已经很久了,最近找到了,并且通过测试。
1、首先自己创建manifest文件,并添加到工程中。
2、在资源文件中添加
“CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "xxxxx.exe.manifest"”。
3、在创建的manifest文件中添加。
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
到此,提成权限结束。这样你就可一个操作一些和系统相关的信息了。
如果,在xp上开发,按照上述的操作后在编译的时候会出现操作系统重起现象。个人分析,是因为自己创建的manifest文件和编译后自动生成的manifest文件冲突。
二、当前路径的取得和设置
GetModuleFileName函数取得当前进程的路径。
SetCurrentDirectory函数改变当前进程的路径。
三、取得当前计算机电源的使用状态。
GetSystemPowerStatus函数填充SYSTEM_POWER_STATUS结构体。通过这个结构体中的参数判断当前计算机的供电状态。
如果是使用笔记本,当插拔外接电源时会触发WM_POWERBROADCAST消息。通过wParam参数判断状态。
四、设置窗口为最顶端窗口和把最顶端窗口后置。
设置窗口成为顶窗口,有两种方法。
1、使用BOOL SetForegroundWindow(HWND hWnd)函数传入置顶窗口的句柄,成功返回真。
2、使用SetWindowPos(...)。第一个参数是,置顶窗口的句柄;第二个参数是,在z序中的位于被置位的窗口前的窗口句柄。选择HWND_TOPMOST即可。
把最顶窗口后置。
HWND hWin = ::GetForegroundWindow();
CRect rect;
BOOL bflag = TRUE;
::GetWindowRect(hWin, &rect);
::SetWindowPos(hWin, HWND_NOTOPMOST, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOSIZE);
CRect rect;
BOOL bflag = TRUE;
::GetWindowRect(hWin, &rect);
::SetWindowPos(hWin, HWND_NOTOPMOST, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOSIZE);
说明:首先取得顶窗口的句柄,然后根据句柄取得窗口的尺寸,最后通过SetWindowPos设定窗口的位置。
五、取得ICON图标的大小
首先,加载ICON图标取得ICON句柄
HICON hIcon = ExtractIcon(::AfxGetInstanceHandle(), strPath.Trim().GetBuffer(MAX_PATH), 0);
取得ICON图标大小
if(NULL != hIcon )
{
ICONINFO IconInfo;
BITMAP bm;
GetIconInfo(hIcon, &IconInfo);
GetObject(IconInfo.hbmColor, sizeof(bm), &bm);
{
ICONINFO IconInfo;
BITMAP bm;
GetIconInfo(hIcon, &IconInfo);
GetObject(IconInfo.hbmColor, sizeof(bm), &bm);
}
BITMAP结构体中的成员包含ICON的宽和高。
注:使用ExtractIcon这个函数还可以取得指定文件的Icon句柄。
六、字体大小的单位转换(point to pixel)
在程序中处理字体时,需要指定使用pixel为单文的尺寸。但在实际应用中,一般都指定以point为单位的尺寸。这样,就需要一种单位转换,从point到pixel。
例:求9point 的字体的高度
CClientDC dc(AfxGetMainWnd());
int nFontheight = MulDiv(9, dc.GetDeviceCaps(LOGPIXELSY), 72);
七、菜单项的响应
在使用AppendMenu函数添加菜单项的时候需要指定菜单项的ID,每一个菜单项的ID 不能重复。然后,创建一个函数用来响应菜单项的事件,其参数是UINT ID。最后,添加ON_COMMAND_RANGE消息响应事件,第一个参数为菜单项的起始ID值,第二个参数为菜单项的结束ID值,第三个参数为处理函数地址。
如:
//添加菜单项
CMenu mnu;
CMenu mnuSub;
mnu.AppendMenu(MF_STRING|MF_OWNERDRAW,10,"Item 1");
mnu.CreatePopupMenu();
mnuSub.AppendMenu(MF_STRING|MF_OWNERDRAW,20,"Item 1 - submenu");
mnuSub.AppendMenu(MF_STRING|MF_OWNERDRAW,21,"Item 2 - submenu");
mnu.AppendMenu(MF_POPUP|MF_OWNERDRAW,(UINT)mnuSub.GetSafeHmenu(),"Sub Menu");
mnu.CreatePopupMenu();
mnuSub.AppendMenu(MF_STRING|MF_OWNERDRAW,20,"Item 1 - submenu");
mnuSub.AppendMenu(MF_STRING|MF_OWNERDRAW,21,"Item 2 - submenu");
mnu.AppendMenu(MF_POPUP|MF_OWNERDRAW,(UINT)mnuSub.GetSafeHmenu(),"Sub Menu");
mnu.AppendMenu(MF_STRING|MF_OWNERDRAW,11,"Item 2");
//创建响应函数
void CDemoDlg::MenuHandler(UINT id)
{
{
switch(id)
{
{
case 10:
MessageBox("Item 1","Item 1");
break;
case 11:
MessageBox("Item 2","Item 2");
break;
MessageBox("Item 1","Item 1");
break;
case 11:
MessageBox("Item 2","Item 2");
break;
case 20:
MessageBox("Item 20","Item 1 - submenu");
break;
MessageBox("Item 20","Item 1 - submenu");
break;
case 21:
MessageBox("Item 21","Item 2 - submenu");
break;
MessageBox("Item 21","Item 2 - submenu");
break;
}
}
//添加响应消息
ON_COMMAND_RANGE(10,21,MenuHandler)
八、窗口过程函数必须是全局的
项目中需要封装一个功能dll,并且这个dll还要处理操作系统发出的消息。于是,在这个功能类中添加创口过程函数(WndProc)作为这个功能类的成员函数。编译时出错,后来重新Review之后,发现到了问题。原因就是这个窗口过程函数不是全局的。把这个作为成员函数出现的窗口过程函数改造成静态的成员函数,问题解决。
方法一:
LPCTSTR lpStr = NULL;
String str = ”Convert”;
lpStr = (LPCTSTR)Marshal::StringToHGlobalAuto(str).ToPointer;
方法二:
LPCTSTR lpStr = NULL;
String str = ”Convert”;
lpStr =static_cast< LPCTSTR >(const_cast<void*>( static_cast<const void*>( Marshal::StringToHGlobalAuto(str))));
然后还需要进行释放。
Marshal::FreeHGlobal(static_cast<IntPtr>(onst_cast<void*>(static_cast<const void*>( lpStr))));
这才算是完成,呵呵。
十一、阻止响应ESC键
在程序中添加响应函数PreTranslateMessage。做下面处理:
BOOL C******::PreTranslateMessage(MSG* pMsg)
{
{
// TODO: Add your specialized code here and/or call the base class
if( pMsg->message == WM_KEYDOWN )
{
switch(pMsg->wParam)
{
case VK_ESCAPE:
return TRUE;
}
}
if( pMsg->message == WM_KEYDOWN )
{
switch(pMsg->wParam)
{
case VK_ESCAPE:
return TRUE;
}
}
return CPropertySheet::PreTranslateMessage(pMsg);
}
}
十二、阻止Alt+F4
在程序中添加响应函数OnSysCommand。做下面处理:
void C********::OnSysCommand(UINT nID, LPARAM lParam)
{
// TODO: Add your message handler code here and/or call default
{
// TODO: Add your message handler code here and/or call default
if(nID==SC_CLOSE && lParam==0)
{
return;
}
{
return;
}
CPropertySheet::OnSysCommand(nID, lParam);
}
}
十三、取得当前的临时文件夹
很多时候我们需要把一些中间文件存放到系统的临时文件夹中。我们可以这样取得:
TCHAR chTemp[1024] = {0};
TCHAR chTempConver[1024] = {0};
::GetTempPath(1024, chTemp);
::GetLongPathName( chTemp, chTempConver, 1024 );
TCHAR chTempConver[1024] = {0};
::GetTempPath(1024, chTemp);
::GetLongPathName( chTemp, chTempConver, 1024 );
十四、判断驱动器是否存在,并识别驱动器类型
使用
GetDriverType函数可以完成这个功能。
十五、在操作系统启动时启动某些程序
实现开机启动的方法有多种,我使用修改注册表的方式来实现。这个比较容易,呵呵。
如果针对某个用户,修改:HKCU/SOFTWARE/Microsoft/Windows/CurrentVision/run
如果针对所有用户,修改:HKLM/SOFTWARE/Microsoft/Windows/CurrentVision/run
十六、