桌面时钟(GDI实现) 学习总结

// 很完整的在对话框上绘制矩形的格式
void ScaleSetDlg::OnPaint()
{
CPaintDC dc(this);
CPen penBorder(PS_SOLID,1,RGB(255,255,255));
CPen *ppenOld = dc.SelectObject(&penBorder);
CBrush brPoint(m_color);
CBrush* pbrOld = dc.SelectObject(&brPoint);


dc.Rectangle(180,55,240,85);


dc.SelectObject(ppenOld);
dc.SelectObject(pbrOld);
}




// 很完整的在对话框上 贴图(Bitmap格式)

CBitmap maskbmp,logbmp;
maskbmp.LoadBitmap(IDB_LOGMASK);
logbmp.LoadBitmap(IDB_LOG);


CDC MaskDC,memDC;
MaskDC.CreateCompatibleDC(pDc);
MaskDC.SelectObject(&maskbmp);
memDC.CreateCompatibleDC(pDc);
memDC.SelectObject(&logbmp);
// 不知道为什么要两个同时弄,可能是需要混合原来的颜色
pDc->BitBlt(m_ptMiddle.x - 25 ,ptMiddle.y - nRidius * 0.7,96,96,&MaskDC,0,0,SRCAND);
pDc->BitBlt(m_ptMiddle.x - 25,ptMiddle.y - nRidius * 0.7,96,96,&memDC,0,0,MERGEPAINT);


// 精确的求出 刻度的位置
CPoint CClockScale::ComputerFacePoint(UINT min, int nFaceLength)
{
CPoint ptCalc;
//将分钟转换为角度数 , 这段核心的代码看不懂
double fDegrees = 180+((15+min)%60)*6;


//再转换为弧度数
double fAngle = fDegrees/180;


//计算刻度点位置


ptCalc.x = m_ptMiddle.x + (int)(cos(fAngle*PI)*nFaceLength);
ptCalc.y = m_ptMiddle.y + (int)(sin(fAngle*PI)*nFaceLength);


//返回刻度点位置
return(ptCalc);
}


// 矩形可以随意扩展,很好的函数,  还有可以画一个 3d的矩形,也不错
CRect rectPoint(ptFace.x,ptFace.y,ptFace.x,ptFace.y);
rectPoint.InflateRect(1,1);
pDC->Draw3dRect(&rectPoint,GetSysColor(COLOR_BTNHIGHLIGHT),GetSysColor(COLOR_BTNSHADOW));


// 根据多边形画法,画出三角形 和 圆形
CPoint ptRhombus[4] ;
case TYPE_RHOMBUS:
oldPen = pDC->SelectObject(&penBorder);
ptRhombus[1].x = rectPoint.left + rectPoint.Width()/2;
ptRhombus[1].y = rectPoint.top;

ptRhombus[0].x = rectPoint.left;
ptRhombus[0].y = rectPoint.top + rectPoint.Height()/2;


ptRhombus[3].x = rectPoint.left + rectPoint.Width()/2;
ptRhombus[3].y = rectPoint.bottom;


ptRhombus[2].x = rectPoint.right;
ptRhombus[2].y = rectPoint.top + rectPoint.Height()/2;


pDC->Polygon(ptRhombus,4);
pDC->SelectObject(oldPen);
break;
case TYPE_TRIANGLE:
oldPen = pDC->SelectObject(&penBorder);
ptRhombus[0].x = rectPoint.left;
ptRhombus[0].y = rectPoint.top + rectPoint.Height()/2;

ptRhombus[1].x = rectPoint.left + rectPoint.Width()/2;
ptRhombus[1].y = rectPoint.top;

ptRhombus[2].x = rectPoint.right;
ptRhombus[2].y = rectPoint.top + rectPoint.Height()/2;


pDC->Polygon(ptRhombus,3);
pDC->SelectObject(oldPen);
break;




// 颜色对话框,格式,模板。。
void HandSetDlg::OnHcolor() 
{
CColorDialog dlg;
dlg.m_cc.Flags|=CC_RGBINIT ; // 颜色对话框属性
dlg.m_cc.rgbResult=m_HColor; // 当前时针边框颜色显示到颜色对话框上
if(IDOK==dlg.DoModal())
{
  m_HColor = dlg.m_cc.rgbResult; // 获取用户选择的颜色

}




// 遇到了一个问题,改错误没有直接说明哪里错误,原来是 在类中 只有声明,没有定义
1>C:\Users\Administrator\Desktop\VSCode\DeskClock_Copy\Debug\DeskClock_Copy.exe : fatal error LNK1120: 1 个无法解析的外部命令



// 窗口全屏


WINDOWPLACEMENT m_OldWndPlacement; //用来保存原窗口位置
bool m_bFullScreen;//全屏显示标志


void CDeskClockDlg::OnFull() 
{
if(m_bFullScreen)
{ //退出全屏显示, 恢复原窗口显示
ShowWindow(SW_HIDE);
SetWindowPlacement(&m_OldWndPlacement);
m_bFullScreen = false;
}
else
{
GetWindowPlacement(&m_OldWndPlacement);
CRect WindowRect;
GetWindowRect(&WindowRect);
CRect ClientRect;
RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery, &ClientRect);
ClientToScreen(&ClientRect);
// 获取屏幕的分辨率
int nFullWidth=GetSystemMetrics(SM_CXSCREEN);
int nFullHeight=GetSystemMetrics(SM_CYSCREEN);
//将除控制条外的客户区全屏显示到从(0,0)到(nFullWidth, nFullHeight)区域, 将(0,0)和(nFullWidth, 


nFullHeight)两个点外扩充原窗口和除控制条之外的 客户区位置间的差值, 就得到全屏显示的窗口位置
m_FullScreenRect.left=WindowRect.left-ClientRect.left;
m_FullScreenRect.top=WindowRect.top-ClientRect.top;
m_FullScreenRect.right=WindowRect.right-ClientRect.right+nFullWidth;
m_FullScreenRect.bottom=WindowRect.bottom-ClientRect.bottom+nFullHeight;
m_bFullScreen=TRUE; //设置全屏显示标志为 TRUE
//进入全屏显示状态
WINDOWPLACEMENT wndpl;
wndpl.length=sizeof(WINDOWPLACEMENT);
wndpl.flags=0;
wndpl.showCmd=SW_SHOWNORMAL;
wndpl.rcNormalPosition=m_FullScreenRect;
SetWindowPlacement(&wndpl);
}
Invalidate();
}


// 双缓冲步骤
CRect rectClient;
GetClientRect(&rectClient);
CPaintDC dc(this);


CDC memDC;
memDC.CreateCompatibleDC(&dc);


m_ClockScale.DrawScale(&memDC,m_ptMiddle);

dc.StretchBlt(0,0,rectClient.Width(),rectClient.Height(),&memDC,0,0,rectClient.Widt(),rectClient.Height (),SRCCOPY);



本章设计的技术点如下:

1、利用GDI技术绘制图形图像

2、利用双缓冲技术消除闪屏

3、通过蜂鸣器播放音乐

4、利用多线程编程播放音乐

5、通过颜色对话框选择图形色彩

6、利用定时器技术实现时钟时间的实时更新


总结:

大概过了一遍这个例子,开始的时候方法不对,不知道从哪里下手,因为自己想要重新复制一次代码,走了一点弯路,后来才找对门路。

如何看这类型的代码:

a:根据主对话框上面的 绘图(OnPaint)依次顺序往下看实现

b:每个对话框都有相应的类和属性类(普通对话框),其中属性类这个想法特别漂亮,节约了对话框类的大量代码,使代码的层次更加的清晰分明。

c:但是,自己还是走了错路,就是先看了属性类,应该先看对话框类,再看属性类,因为属性类是根据对话框类变化而变化的。 之所以会走这条错路,还是得回到

a中,因为自己是从那里开始看代码,而属性类就包含了 绘画(Draw),所以,就引到了另一条错路。

总的来说,这次的学习是对过去学习的一个小回顾,虽然还有许多小细节没有完成,但这就算是一个小开始吧,后面还有许多以小项目为基础的学习,希望到时候能更加的冷静,淡定,不急躁,多观察,多思考,一心一意,脚踏实地,扎扎实实,直到完全理解了才进入到下一个阶段


你可能感兴趣的:(桌面时钟(GDI实现) 学习总结)