QQ 界面编程之鸡蛋里挑骨头,QQ 界面编程之鸡蛋里挑骨头
QQ 界面编程之鸡蛋里挑骨头
作者:韩山师范学院02届黄锐坤
下载源代码
新的一年即将来临,新版本的QQ估计也要跟我们相见。在此献上本人写于8月份的一个练习程序。主要是希望腾讯做界面的同志能否把创建异形窗体函数 SetWindowRgn 放到合适的位置,别让拖动窗体改变大小时出现用做 MASK 的紫色区域;再者与大家分享不指定窗体风格 WS_THICKFRAME(对于对话框,相当指定其属性 Border 为 Resizing ),用代码实现窗体拖放,任意改变其尺寸。
一、SetWindowRgn的合适位置
1、在void C**Dlg::OnPaint()里调用SetWindowRgn
可以在内存画图完毕准备显示到屏幕前调用,如下:
void C**Dlg::OnPaint(){ if (IsIconic()) {CPaintDC dc(this);... } else {CPaintDC dc(this); // 用于绘制的设备上下文CRect rcClient;GetClientRect(&rcClient);//构造内存DC,用于画图CDC m_MemDC;(&) btScreen;(&dc, (), ());(&)()这里画图创建不规则窗体(&)这里面调用了画到显示器上(, rcClient.top, (), (), &m_MemDC, 0, 0, SRCCOPY);(); }}void C**Dlg::ChangeWindowRgn(CDC *pDC){ COLORREF col = RGB(255,0,255); CRect rcClient; GetClientRect (rcClient); CRgn rgn; (0, 0, (), ()); ...SetWindowRgn (rgn, TRUE);}
2、在void C**Dlg::OnShowWindow()里调用SetWindowRgn, 如下:
void C**Dlg::OnShowWindow(BOOL bShow,UINT nStatus){ CWnd::OnShowWindow(bShow, nStatus); // TODO: 在此处添加消息处理程序代码 if(bShow) {CRect rc;this-GetClientRect(&rc);CRgn rgnMain;(0, 0, (), ());...SetWindowRgn( rgnMain, TRUE ); }}
二、手动做“Resizing对话框”
该思路启发于徐景周的精灵特效窗体。要想点击窗体客户区不放能移动窗体,传统的做法是模拟消息点击标题。
void C**Dlg::OnLButtonDown(UINT nFlags, CPoint point){ // TODO: 在此添加消息处理程序代码 PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,0);CDialog::OnLButtonDown(nFlags, point);}
这样很方便实现效果。但不足是窗体被移到屏幕上方,大部分在屏幕所能显示以外以后放开鼠标,窗体会自动向下对齐。徐景周的精灵特效窗体用了SetTimer和MoveWindow结合使用,这样窗体想被移到哪里都可以。正因为如此,让我想到拖放窗体的好思路。当然我们完全可以利用窗体风格WS_THICKFRAME,让系统来为我们做事。
但是如果我们要指定窗体某个部位可以拖放窗体时,像QQ切换主题后,拖放很不方便。可以拖放的区域不是最左,最右,最上,最下,没有别的地方可以点击拖放窗体了。
如何实现,简单说就是在鼠标按下时判断是否点在规定区域内,是的话启动记时器。然后在记时器里面定时器里面对光标判断当前位置与之前位置,从而调用MoveWindow让窗体朝响应方向拉伸或收缩。代码较琐碎,请见例子。
void C**Dlg::OnLButtonDown(UINT nFlags, CPoint point){ CRect rc(*,*,*,*); if(()) {SetTimer(1,20,NULL);//启动记时器return; } CDialog::OnLButtonDown(nFlags, point);}void C**Dlg::OnTimer(UINT_PTR nIDEvent){ // TODO: 在此添加消息处理程序代码和/或调用默认值 switch(nIDEvent) { case(1): {CRect rcW;POINT point;GetWindowRect(rcW);////实现拖动时窗体跟着右下角拉伸::GetCursorPos(&point); //得到“当前位置”if(point.y<){ MoveWindow( ,point.y-m_ptCurPoint.y, (), m_rcCurRect.bottom-(point.y-m_ptCurPoint.y), true); CRect rc; GetWindowRect(rc); m_rcCurRect = rc;//保存“之前位置”}Invalidate(); } break; ... Default:break; } Dialog::OnTimer(nIDEvent);}
代码在Visual下编译,在WindowXP运行通过。预览图如下:
预览图