3
l 改变背景色:在OnCtlColor()函数中实现,OnCtlColor()函数是被调用多次,在每一个控件绘背景色的时候调用,在OnCtlColor()中捕获特定控件的ID,通过参数中的DC进行操作绘图。这个函数不能对Button的背景色进行改变。
l 改变按键的背景色:创建新的类,继承Cbutton,重载DrawItem()和Attach()达到重绘的作用,使用新类为按键的类型,记住修改按键的属性为OwnDraw。(好好理解)
void CMybtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
UINT state = lpDrawItemStruct->itemState;
CRect focusRect,btnRect;
focusRect.CopyRect(&lpDrawItemStruct->rcItem);
btnRect.CopyRect(&lpDrawItemStruct->rcItem);
focusRect.left +=4;
focusRect.right -= 4;
focusRect.top +=4;
focusRect.bottom -=4;
const int buffSize = 512;
TCHAR buffer[buffSize];
GetWindowText(buffer,buffSize);
pDC->Draw3dRect(&btnRect,m_fg,m_bg);
pDC->FillRect(&btnRect,&CBrush(RGB(255,255,255)));
pDC->DrawText(buffer,&btnRect,DT_CENTER);
if(state & ODS_FOCUS)
{
pDC->Draw3dRect(&focusRect,m_fg,m_bg);
pDC->FillRect(&focusRect,&CBrush(RGB(0,255,0)));
if(state & ODS_SELECTED)
{
pDC->Draw3dRect(&btnRect,m_fg,m_bg);
pDC->FillRect(&btnRect,&CBrush(RGB(0,0,255)));
}
}
else if (state & ODS_DISABLED)
{
pDC->Draw3dRect(&btnRect,m_disabled_fg,m_disabled_dg);
pDC->FillRect(&btnRect,&CBrush(RGB(255,0,0)));
}
}
BOOL CMybtn::Attach(const UINT nID,CWnd* pParent)
{
GetDlgItem(nID)->ModifyStyle(0,BS_OWNERDRAW,0);
if(!SubclassDlgItem(nID,pParent))
return FALSE;
return TRUE;
}
l 将ico或bmp图贴在按键上,运用CButton中的SetBitmap()和SetIcon()进行操作,注意记得要修改所要改变的按键的相应属性以适应改变。
(AfxGetApp()->LoadIcon() 通过全局对象CwinApp,获取资源的句柄)
l 实现重启、关机、按时关机、强制关机按键
Ø 运用::WinExec()函数,调用shutdown命令的参数实现。-t –s –r
Ø 强制关机的代码(好好理解)
BOOL CTestAllView::OnFshutdown()
{
// TODO: Add your control notification handler code here
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Get a token for this process.
// OpenProcessToken() 这个函数的作用是打开一个进程的访问令牌
// GetCurrentProcess() 函数的作用是得到本进程的句柄
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))
return( FALSE );
// Get the LUID for the shutdown privilege.
// LookupPrivilegeValue() 的作用是修改进程的权限
LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; //one privilege to set 赋给本进程特权
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
// AdjustTokenPrivileges()的作用是通知Windows NT修改本进程的权利
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES)NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
// Shut down the system and force all applications to close.
if (!ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, 0)) //参数在这里设置。 强行退出WINDOWS。
return FALSE;
return TRUE;
}
l 将图片(花)贴满屏幕
我的方法:将窗口最大化,运用WM_TIMER消息,SetTimer()按1秒的间隔将图贴在屏幕。创建兼容于父窗口的DC,BitBlt()贴图,运用GetSystemMetric()获取整个屏幕的大小和rand()随机函数,确定贴图的坐标。最后按下键盘的Esc键调用KillTimer()和Invalidate()结束贴图。运用WM_CHAR(只接受字符与数字)和WM_DOWN(接受虚拟键(VK))捕获按下Esc键的消息,因为对话框得不到系统焦点,捕获不了按键的消息,所以也要手动修改PreTranslateMessage函数的过程。
BOOL CTestAllView::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
::SendMessage(GetSafeHwnd(),pMsg->message,pMsg->wParam,pMsg->lParam);
return CFormView::PreTranslateMessage(pMsg);
}
问题: 如何获取程序外桌面的DC?