使用MFC编制基于对话框的Windows应用程序,实现画图功能

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用MFC编制基于对话框的Windows应用程序,实现画图功能相关的知识,希望对你有一定的参考价值。

(1)画直线:通过CDC:LineTo()函数实现。
(2)画曲线:通过CDC:LineTo()函数实现。
(3)画矩形:通过Rectangle()函数实现。
(4)利用位图资源填充矩形:通过CBrush类构造函数CBrush(Bitmap*)实现。
(5)画扇形:通过CDC:LineTo()函数实现
(6)设置透明的刷子(将矩形填充色为透明)。
(7)窗口在重绘时不擦出原来的内容:在窗口发生变化时,窗口的内容不消失,程序在窗口尺寸发生变化时,将会发送WM_PAINT消息,这时首先会擦出窗口背景,然后进行重绘操作,这样就把窗口中先前绘制的内容擦除掉了。

参考技术A 获取对话框的窗口句柄 创建你的绘制图层并将句柄绑定在图层上
画几何图形操作都基于图层来画
最后将画好的图层贴在DLG上就行了
参考技术B 见邮箱本回答被提问者采纳 参考技术C 士大夫

OpenGL 抑制基于 MFC 对话框的应用程序中的异常

【中文标题】OpenGL 抑制基于 MFC 对话框的应用程序中的异常【英文标题】:OpenGL suppresses exceptions in MFC dialog-based application 【发布时间】:2010-01-29 15:25:45 【问题描述】:

我有一个使用 MSVS2005 创建的 MFC 驱动的基于对话框的应用程序。这是我的问题一步一步。我的对话框和相应的点击处理程序上有按钮,代码如下:

int* i = 0;
*i = 3;

我正在运行调试版本的程序,当我单击按钮时,Visual Studio 捕捉焦点并警告“访问冲突写入位置”异常,程序无法从错误中恢复,我所能做的就是停止调试。这是正确的行为。

现在我在OnInitDialog()方法中添加一些OpenGL初始化代码:

    HDC DC = GetDC(GetSafeHwnd());
    static PIXELFORMATDESCRIPTOR pfd =
    
      sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
      1, // version number
      PFD_DRAW_TO_WINDOW | // support window
      PFD_SUPPORT_OPENGL | // support OpenGL
      PFD_DOUBLEBUFFER, // double buffered
      PFD_TYPE_RGBA, // RGBA type
      24, // 24-bit color depth
      0, 0, 0, 0, 0, 0, // color bits ignored
      0, // no alpha buffer
      0, // shift bit ignored
      0, // no accumulation buffer
      0, 0, 0, 0, // accum bits ignored
      32, // 32-bit z-buffer
      0, // no stencil buffer
      0, // no auxiliary buffer
      PFD_MAIN_PLANE, // main layer
      0, // reserved
      0, 0, 0 // layer masks ignored
    ;

    int pixelformat = ChoosePixelFormat(DC, &pfd);
    SetPixelFormat(DC, pixelformat, &pfd);

    HGLRC hrc = wglCreateContext(DC);
    ASSERT(hrc != NULL);
    wglMakeCurrent(DC, hrc);

当然,这不完全是我所做的,它是我的代码的简化版本。那么现在奇怪的事情开始发生:所有初始化都很好,OnInitDialog() 没有错误,但是当我单击按钮时......没有抛出异常。没发生什么事。完全没有。如果我在*i = 3; 处设置断点并在其上按 F11,则处理程序函数会立即停止并将焦点返回到应用程序,该应用程序继续运行良好。我可以再次单击按钮,同样的事情会发生。

似乎有人已经处理了发生的访问冲突异常,并默默地将执行返回到主应用程序消息接收周期。

如果我注释 wglMakeCurrent(DC, hrc); 行,一切正常,抛出异常,Visual Studio 捕获它并显示带有错误消息的窗口,然后必须终止程序。

我在安装了网站上提供的最新驱动程序(2010 年 1 月 11 日)的 Windows 7 64 位、NVIDIA GeForce 8800 下遇到了这个问题。我的同事使用的是 32 位 Windows Vista 并且没有这样的问题 - 在这两种情况下都会引发异常并且应用程序崩溃。

好吧,希望好人能帮助我:)

PS 这个问题最初是在this 主题下发布的。

【问题讨论】:

这很有趣,我最近遇到了同样的问题......如果你将异常抛出代码包装在 try-catch 块中,它会在那里捕获异常,但如果异常传播到 MFC代码它似乎被吞没了。我想一个潜在的解决方法是自己使用 try-catch 块。 我可以确认这个问题,它与 windows vista 64 位和 windows 7 64 位上的 OpenGL 有关。自己寻找答案:) 这似乎与我的问题相似:***.com/questions/2622200/… 【参考方案1】:

好的,我发现了一些关于此的更多信息。在我的情况下,Windows 7 安装 KiUserCallbackExceptionHandler 作为异常处理程序,然后调用我的 WndProc 并给我执行控制权。这是由 ntdll!KiUserCallbackDispatcher 完成的。我怀疑这是微软为防止黑客入侵 SEH 而采取的安全措施。

解决方案是使用 try/except 框架包装您的 wndproc(或 hookproc),以便您可以在 Windows 之前捕获异常。

感谢 Skywing http://www.nynaeve.net/

我们已经就此事联系了 nVidia 问题,但他们说这不是他们的 bug,而是微软的。可以 请告诉您您是如何找到 异常处理程序?你有吗 一些附加信息,例如一些 来自微软的反馈?

我使用 WinDbg 中的“!exchain”-命令来获取此信息。

【讨论】:

我们已经就这个问题联系了 nVidia,但他们说这不是他们的错误,而是微软的错误。你能告诉你如何找到异常处理程序吗?你有没有一些额外的信息,例如来自微软的一些反馈?【参考方案2】:

您可以使用向量异常处理,而不是包装 WndProc 或挂钩所有 WndProc:

http://msdn.microsoft.com/en-us/library/ms679274.aspx

【讨论】:

我收回了。我们不得不恢复这种变化,因为它过于激进。有一些异常我们想不理会并允许以正常方式处理,但我们无法将它们与我们想要崩溃的访问冲突等区分开来。 我有一个用于所有用户界面的基类,它用 __try / __catch 覆盖 WndProc。然后处理程序在发布时调用崩溃报告器,在调试中它会继续,以便我们可以调试崩溃。 经过进一步调查,我们发现我们的问题实际上是在 64 位操作系统上运行 32 位程序的 Windows 错误。有一篇关于堆栈溢出的单独文章,我认为这也是原始海报的真正问题。【参考方案3】:

首先,这两种行为都是正确的。取消引用空指针是“未定义的行为”,而不是保证访问冲突。

首先,找出这是否与异常抛出有关或仅与访问内存位置零有关(尝试不同的异常)。

如果您将 Visual Studio 配置为在首次访问违规时停止,它会中断吗?

在 glMakeCurrent 前后调用 VirtualQuery(NULL, ...) 并进行比较。也许 nVidia OpenGL 驱动程序 VirtualAlloc 页面为零(一个坏主意,但并非不可能或非法)。

【讨论】:

任何异常的行为相同,包括使用 throw 运算符手动引发。如果我将 Visual Studio 配置为在第一次出现异常时停止,它就会中断。 听起来像向量异常处理程序已注册并吃掉异常。 msdn.microsoft.com/en-us/library/ms681420(VS.85).aspx 在第一次出现异常时中断,然后开始单步执行(确保禁用“仅我的代码”选项,以便您可以单步执行其他库)。可能某些处理程序返回 EXCEPTION_CONTINUE_EXECUTION 而不是 EXCEPTION_CONTINUE_SEARCH。 VirtualQuery(NULL, ...)比较结果,wglCreateContext()前后调用结果相同。 VirtualQuery 假设是为了在 NULL 指针异常未触发但其他异常触发时进行故障排除。由于您已吞下所有异常,因此请逐步执行向量异常处理程序。您至少应该了解哪些 DLL 包含处理程序以及为什么您的两个系统之间的行为不同。 我不确定是不是这样。我认为马克英格拉姆的评论更接近目标。矢量异常处理似乎是解决方案,而不是问题。我遇到了同样的问题,我添加了一个处理程序,它发出一个 appfatal 并让它在异常时崩溃。在添加之前,我无法设法进入向量化异常处理。一旦我添加了一个,我就可以进入它,这让我相信我的处理程序是唯一的,通过崩溃处理是获得这种行为的正确方法。【参考方案4】:

我在查看类似问题时发现了这个问题。我们的问题原来是在 64 位 Windows 上运行 32 位应用程序时静默消耗异常。

http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

Microsoft 提供了一个修复程序,但如果您有多个目标平台,部署它会有些挑战:

http://support.microsoft.com/kb/976038

这是一篇关于描述行为的主题的文章:

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

堆栈溢出的这个线程也描述了我遇到的问题: Exceptions silently caught by Windows, how to handle manually?

【讨论】:

以上是关于使用MFC编制基于对话框的Windows应用程序,实现画图功能的主要内容,如果未能解决你的问题,请参考以下文章

无法在基于 MFC 对话框的应用程序中使用 SetDlgItemTextW() 设置对话框的标题

MFC 使用Skin++ 美化皮肤

更改 MFC 对话框元素的背景颜色

尝试创建基于 MFC 对话框的应用程序来读取视频

基于 mfc 对话框的应用程序中的功能区控件

MFC 对话框应用程序未关闭