***请教有关自绘 Windows 窗口的问题***

Aizz 2002-10-15 05:40:48

想请教各位:

如果我想实现一个自己绘制的窗口(包括标题栏、边框等窗口内的标准元素都是自己绘制),那么我需要自己写一个General Class还是可以从CWnd继承,然后对CWnd里的东西做手术呢?

我查了查VC里有关CWnd的类定义,好像只有函数的定义,找不到实现的代码。另外似乎控件的Draw函数里画边框用到的是DrawEdge(),而DrawEdge()也没有源代码,不知道M$是怎么画的,呵呵。

哪位有经验的,请指教,谢谢!
...全文
57 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Aizz 2002-10-17
  • 打赏
  • 举报
回复

非常感谢 everandforever 和 jennyvenus 的回复。

谢谢 everandforever 的提示,也谢谢 jennyvenus 的源代码。

如果我遇到什么问题再开帖子向各位请教,呵呵。

真的非常感谢!
用户 昵称 2002-10-16
  • 打赏
  • 举报
回复
//重画还原最大化button
rtButtons.left = rtTitle.right - 18-17-2;
rtButtons.top = rtTitle.top-3;
rtButtons.right = rtButtons.left + 17;
rtButtons.bottom = rtButtons.top + 17;
pBitmap->LoadBitmap(IDB_CAPTIONBAR);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
if (IsZoomed())
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 294, 6, SRCCOPY);
else
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 342, 6, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
m_rtButtMax = rtButtons;
m_rtButtMax.OffsetRect(rtWnd.TopLeft());
pBitmap->DeleteObject();

//重画最小化button
pDC->SetBkMode(TRANSPARENT);
rtButtons.left = rtTitle.right - 18-17-17-2;
rtButtons.top = rtTitle.top-3;
rtButtons.right = rtButtons.left + 17;
rtButtons.bottom = rtButtons.top + 17;
pBitmap->LoadBitmap(IDB_CAPTIONBAR);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 393, 6, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
m_rtButtMin = rtButtons;
m_rtButtMin.OffsetRect(rtWnd.TopLeft());
pBitmap->DeleteObject();

//画左边界
rtTitleBar.left = 0;
rtTitleBar.top = 48;
rtTitleBar.right = 10;
rtTitleBar.bottom = 10;
pBitmap->LoadBitmap(IDB_BOARDS);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
while (rtTitleBar.top<rtWnd.Height())
{
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 0, 0, SRCCOPY);
rtTitleBar.top+=10;
}
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画右边界
rtTitleBar.left = rtWnd.Width()-9;
rtTitleBar.top = 48;
rtTitleBar.right = 10;
rtTitleBar.bottom = 10;
pBitmap->LoadBitmap(IDB_BOARDS);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
while (rtTitleBar.top<rtWnd.Height())
{
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 40, 0, SRCCOPY);
rtTitleBar.top+=10;
}
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画底边界
rtTitleBar.left = 0;
rtTitleBar.top = rtWnd.Height()-9;
rtTitleBar.right = 10;
rtTitleBar.bottom = 10;
pBitmap->LoadBitmap(IDB_BOARDS);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
while (rtTitleBar.left<rtWnd.Width())
{
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 30, 0, SRCCOPY);
rtTitleBar.left+=10;
}
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画左下边界
rtTitleBar.left = 0;
rtTitleBar.top = rtWnd.Height()-9;
rtTitleBar.right = 10;
rtTitleBar.bottom = 10;
pBitmap->LoadBitmap(IDB_BOARDS);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 20, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画右下边界
rtTitleBar.left = rtWnd.Width()-9;
rtTitleBar.top = rtWnd.Height()-9;
rtTitleBar.right = 10;
rtTitleBar.bottom = 10;
pBitmap->LoadBitmap(IDB_BOARDS);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 60, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//图表位置,出菜单
rtButtons.left = 10;
rtButtons.top = 3;
rtButtons.right = rtButtons.left + 17;
rtButtons.bottom = rtButtons.top + 17;
m_rtIcon = rtButtons;
m_rtIcon.OffsetRect(rtWnd.TopLeft());

ReleaseDC(pDisplayMemDC);
delete pDisplayMemDC;
delete pBitmap;
}
}

第一个帖子是一个例子,2、3是另外一个
用户 昵称 2002-10-16
  • 打赏
  • 举报
回复
void CTitleBarDlg::DrawTitleBar(CDC *pDC)
{
if (m_hWnd)
{
CBrush Brush(RGB(20,201,24));
CBrush* pOldBrush = pDC->SelectObject(&Brush);

CRect rtWnd, rtTitle, rtButtons, rtTitleBar;
GetWindowRect(&rtWnd);
//取得标题栏的位置
rtTitle.left = GetSystemMetrics(SM_CXFRAME);
rtTitle.top = GetSystemMetrics(SM_CYFRAME);
rtTitle.right = rtWnd.right - rtWnd.left - GetSystemMetrics(SM_CXFRAME);
rtTitle.bottom = rtTitle.top + GetSystemMetrics(SM_CYSIZE);

//准备画标题栏
CBitmap* pBitmap = new CBitmap;
CBitmap* pOldBitmap;
CDC* pDisplayMemDC=new CDC;
pDisplayMemDC->CreateCompatibleDC(pDC);

//画标题栏左上角
rtTitleBar.left = 0;
rtTitleBar.top = 0;
rtTitleBar.right = 100;//宽度
rtTitleBar.bottom = 48;
pBitmap->LoadBitmap(IDB_CAPTIONBAR);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
//if (IsWindowUnicode())
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top, rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 0, 0, SRCCOPY);
//else
// pDC->BitBlt(rtTitleBar.left, rtTitleBar.top, rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 576, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画标题栏中间位置
rtTitleBar.left = 100;
rtTitleBar.top = 0;
rtTitleBar.right = 30;
rtTitleBar.bottom = 48;
pBitmap->LoadBitmap(IDB_CAPTIONBAR);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
while (rtTitleBar.left<rtTitle.right)
{
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 100, 0,SRCCOPY);
rtTitleBar.left+=30;
}
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画标题栏文字
CString m_strFontFace="宋体";

LOGFONT lf;
CFont m_fontMe;

lf.lfHeight=12;
lf.lfWidth=0;
lf.lfWeight=700;
lf.lfCharSet=DEFAULT_CHARSET;
lf.lfClipPrecision=CLIP_DEFAULT_PRECIS;
lf.lfEscapement=0;
lf.lfItalic=0;
lf.lfOrientation=0;
lf.lfOutPrecision=OUT_TT_PRECIS;
lf.lfPitchAndFamily=DEFAULT_PITCH;
lf.lfQuality=DEFAULT_QUALITY;
lf.lfStrikeOut=0;
lf.lfUnderline=0;

strcpy(lf.lfFaceName, m_strFontFace);
m_fontMe.CreateFontIndirect(&lf);

int nOldMode = pDC->SetBkMode(TRANSPARENT);
COLORREF clOldText=pDC->SetTextColor(RGB(255, 255, 255));
//pDC->SelectStockObject(SYSTEM_FIXED_FONT);
pDC->SelectObject(&m_fontMe);
rtTitle.left += 100;
rtTitle.top += 5;
rtTitle.bottom = rtTitle.top + 24;
CString m_strTitle;
GetWindowText(m_strTitle);
pDC->DrawText(m_strTitle, &rtTitle, DT_LEFT);
pDC->SetBkMode(nOldMode);
pDC->SetTextColor(clOldText);

//画标题栏右上角
rtTitleBar.left = rtTitle.right-105;
rtTitleBar.top = 0;
rtTitleBar.right = 110;
rtTitleBar.bottom = 48;
pBitmap->LoadBitmap(IDB_CAPTIONBAR);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtTitleBar.left, rtTitleBar.top,rtTitleBar.right, rtTitleBar.bottom, pDisplayMemDC, 130, 0, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
pBitmap->DeleteObject();

//画按钮

//重画关闭button
rtButtons.left = rtTitle.right - 18;
rtButtons.top = rtTitle.top-3;
rtButtons.right = rtButtons.left + 17;
rtButtons.bottom = rtButtons.top + 17;
pBitmap->LoadBitmap(IDB_CAPTIONBAR);
pOldBitmap=(CBitmap*)pDisplayMemDC->SelectObject(pBitmap);
pDC->BitBlt(rtButtons.left, rtButtons.top, rtButtons.Width(), rtButtons.Height(), pDisplayMemDC, 246,6, SRCCOPY);
pDisplayMemDC->SelectObject(pOldBitmap);
m_rtButtExit = rtButtons;
m_rtButtExit.OffsetRect(rtWnd.TopLeft());
pBitmap->DeleteObject();
用户 昵称 2002-10-16
  • 打赏
  • 举报
回复
LRESULT CTitleBarDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lrst=CDialog::DefWindowProc(message, wParam, lParam);

if (!::IsWindow(m_hWnd))
return lrst;

if (message==WM_MOVE||message==WM_PAINT||message == WM_NCACTIVATE||message == WM_NCPAINT ||message == WM_NOTIFY)
{
CDC* pWinDC = GetWindowDC();
if (pWinDC)
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}

return lrst;
}

//响应双击非客户区,就是最大化和恢复
void CTitleBarDlg::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
if (IsZoomed())
SendMessage(WM_SYSCOMMAND, SC_RESTORE, MAKELPARAM(point.x, point.y));
else
{
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(point.x, point.y));
Invalidate();
}
}

void CTitleBarDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
//检测各按钮是否按到
if (m_rtIcon.PtInRect(point))
AfxMessageBox("美丽的窗口!");
else if (m_rtButtHelp.PtInRect(point))
SendMessage(WM_HELP);
else if (m_rtButtExit.PtInRect(point))
SendMessage(WM_CLOSE);
else if (m_rtButtMin.PtInRect(point))
SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, MAKELPARAM(point.x, point.y));
else if (m_rtButtMax.PtInRect(point))
{
if (IsZoomed())
SendMessage(WM_SYSCOMMAND, SC_RESTORE, MAKELPARAM(point.x, point.y));
else
{
SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(point.x, point.y));
Invalidate();
}
}
else if (!IsZoomed())
{
Default();
}
}

void CTitleBarDlg::OnNcMouseMove(UINT nHitTest, CPoint point)
{
//
if (m_rtButtMin.PtInRect(point)||m_rtButtMax.PtInRect(point)||m_rtButtExit.PtInRect(point)||m_rtIcon.PtInRect(point))
{
HCURSOR m_hButtonCursor = AfxGetApp()->LoadCursor(IDC_HAND);
::SetCursor(m_hButtonCursor);
}

CDialog::OnNcMouseMove(nHitTest, point);
}
everandforever 2002-10-16
  • 打赏
  • 举报
回复
从CWND类派生,调用CWND::CREATE函数创建窗口,重载ONPAINT函数自画窗口.
Aizz 2002-10-16
  • 打赏
  • 举报
回复
谢谢 iicup 和 everandforever 的回复。

我找了找WinCore.cpp,好像没有发现实现窗口绘制的代码,有的只是指定一些窗口的Style之类的(也许是我比较愚笨,没有发现,呵呵)。有一个CreateWindow()函数应该是创建窗口的,可惜没有实现。

一些从CWnd继承的象CButton的DrawItem()函数其实是:CWnd::WindowProc()->CWnd::DefWindowProc()->CWnd::CallWindowProc(),之后还是一点儿头绪都没有,Sigh...
还是麻烦各位能不能指出到底我应该要重载哪个函数或者如何做才可以实现自己的窗口的自绘吧。

请指教,谢谢。
everandforever 2002-10-15
  • 打赏
  • 举报
回复
从CWnd继承.至于怎么画,完全是你的事.
双杯献酒 2002-10-15
  • 打赏
  • 举报
回复
MFC都是有代码的.
CWnd的代码在 MFC\SCR\WinCore.cpp里.
您在任何CWnd的函数上,进行单步跟踪(F11)就可以进入。

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧