标签: wm-paint

无效到自己的位图

我想在屏幕外渲染一个控件到一些位图,以便我可以快速访问它.

不幸的是,Control.DrawToBitmap似乎绘制了它所调用的整个控件,包括它的所有子控件.在内部,它向位图发出带有自提供DC的WM_PRINT消息.然后将此临时位图blitting到用户提供的位图.对我来说不可接受,我宁愿根据需要更新这个位图,以便在需要位图时最小化我的性能.

在理想情况下,我希望表单的行为就像它在屏幕上可见(但它不可能).这意味着,如果某个控件的Text属性发生了变化,则表单将部分失效.然后,捕获相关的消息/事件将允许我为要绘制的表单指定我自己的DC,或者简单地将表单DC BitBlt到我自己的DC.

我看过的一些方向:

  • PaintEventArgs参数OnPaint似乎举行成员savedGraphicsState,也许它可以用来找出不需要无效
  • 表单可见但在屏幕区域外.然而,控件不会被绘制.
  • 在窗口上手动调用RedrawWindow(),同样的故事

c# winapi off-screen wm-paint

11
推荐指数
1
解决办法
1066
查看次数

C#中的SetWindowsHookEx

我正试图挂钩第三方应用程序,以便我可以绘制到它的屏幕.在屏幕上绘图是容易的,我需要它没有帮助,但我似乎有使用问题SetWindowsHookEx来处理WH_GETMESSAGE.我无法弄清楚最后两个参数传递的内容.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowDrawer
{
    public partial class Form1 : Form
    {
        private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
        static IntPtr hHook;
        IntPtr windowHandle;
        uint processHandle;

        HookProc PaintHookProcedure;     

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern System.IntPtr FindWindowByCaption(int ZeroOnly, string lpWindowName);

        [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint …
Run Code Online (Sandbox Code Playgroud)

c# setwindowshookex wm-paint

10
推荐指数
2
解决办法
4万
查看次数

有没有什么特别的关于使用BeginPaint/EndPain而不是GetDC/ReleaseDC来响应WM_PAINT消息?

可以使用GetDC/ReleaseDC在窗口的客户区域中绘制.但是响应WM_PAINT消息,必须使用BeginPaint/EndPaint.这有什么特别之处吗?

c++ winapi gdi paint wm-paint

9
推荐指数
3
解决办法
1586
查看次数

如何使用Windows API在透明窗口上绘制动画?

我正在尝试使用Windows API在具有透明背景的窗口上绘制动画.问题是我无法从窗口中删除以前的图形.

我设置了以下参数:

InvalidateRect(m_hWnd, &sClientRect, TRUE);  // we set the bErase parameter as TRUE
paintParams.dwFlags = BPPF_ERASE; // erase window content while copying backbuffer
paintParams.pBlendFunction = &m_sBlendfunc; // copy source image to backbuffer
Run Code Online (Sandbox Code Playgroud)

但它仍然无效.您可以在附加图像中看到结果.我想要的动画是在屏幕上移动圆圈.我得到的(如附图所示)是他们运动的人工制品,因为在每次抽奖之前窗口没有被清除.

请参阅下面的完整代码:

#include "DrawTest.h"

DrawTest* m_sDrawTest;

DrawTest::DrawTest()
{
 m_pAnimation = NULL;
 m_sDrawTest = NULL;
 m_nFrameindex = 0;
}

DrawTest::~DrawTest(void)
{
 if(m_pAnimation)
  delete m_pAnimation;
 m_pAnimation = NULL;
 if(m_sDrawTest)
  delete m_sDrawTest;
 m_sDrawTest = NULL;
}

int DrawTest::Init(AnimationManager* pAnimationManager,HINSTANCE hInstance,int nCmdShow)
{
 //listener
 m_sDrawTest = this;

 //get anemation (sequence of …
Run Code Online (Sandbox Code Playgroud)

c++ windows transparency gdi+ wm-paint

7
推荐指数
1
解决办法
2852
查看次数

收到WM_PAINT后,在VCL/comctl32.dll/USER32.dll/GDI32.dll中偶尔会出现EAccessViolation

我需要一些调试Delphi XE2应用程序崩溃的建议.我自己从来没有见过崩溃 - 事实上它很少发生,并且不能按要求重现.

我们确实从MadExcept获得了一组10个崩溃报告.这些表明主线程在主窗体的列表视图中处理WM_PAINT消息.每种情况下的调用堆栈都没有显示对我自己的代码的引用,只显示了comctl32.dll,ntdll.dll和USER32.dll中的VCL代码和函数.

有问题的列表视图是TColorListView,它派生自TCustomListView,并处理OnCustomDrawItem和OnDeletion事件.但正如我所说,当崩溃发生时,我的TColorListView代码都没有在调用堆栈上.

每种情况下崩溃的实际位置都有所不同,但是通向它的调用顺序(从早到晚)始终是:

KiUserCallbackDispatcher
RtlAnsiStringToUnicodeString
StdWndProc
TWinControl.MainWndProc
TCustomListView.WndProc
TWinControl.WndProc
TControl.WndProc
TCustomListView.WMPaint
TWinControl.WMPaint
TWinControl.WMPaint
TWinControl.DefaultHandler
CallWindowProcA
TControl.WndProc
Run Code Online (Sandbox Code Playgroud)

之后它进入StdWndProc/SendMessageW/TControl.Perform之一,每次路径都不同.最终它最终出现在comctl32.dll,USER32.dll,GDI32.dll或者只是TControl.WndProc中,并引发了EAccessViolation.遗憾的是,我没有关于用户当时尝试做什么的信息,因为用户没有填写错误报告的那一部分.

您能否建议我使用任何"通灵调试"技术来确定崩溃的原因(从而修复它)?


更新以回答以下评论中的问题:

procedure TColorListView.HandleCustomDrawItem(aSender: TCustomListView; aItem: TListItem;
                                              aState: TCustomDrawState; var aDefaultDraw: Boolean);
begin
  Canvas.Font.Color := ItemColors[aItem.Index];
end;
Run Code Online (Sandbox Code Playgroud)

在(仅)其中一个崩溃报告中,它似乎进入TListItem.GetIndex并进一步崩溃了几个堆栈帧.这可能是一个红鲱鱼.

什么是'Perform'ed消息?对不起,我不知道.MadExcept没有给我方法参数值; 只是方法名称.


5月31日

虽然我更愿意根据我的信息找到错误,但我也欢迎我可以添加到程序中的任何新诊断的建议,以便如果在下一个版本之后再次发生这种崩溃,我将会继续.我很茫然,因为在崩溃时我甚至没有修改的代码甚至在调用堆栈上.


6月13日

我在MadExcept报告中添加了一行,告诉我发生异常时应用程序处于什么状态 - Starting/Active/Idle/ModalDlg/Terminated.(感谢Chris Thornton提出的建议.)我认为在关机期间发生异常的可能性是合理的.不幸的是,直到2014年我们才发布新版本并且有可能通过新诊断获取错误报告.

delphi debugging postmortem-debugging wm-paint delphi-xe2

5
推荐指数
1
解决办法
1438
查看次数

在Win32上,我可以禁用一段时间的窗口绘画吗?

是否有一个函数可以冻结窗口重新绘制一段时间,同时我对对话框的布局进行了更改?

c++ windows winapi wm-paint

4
推荐指数
1
解决办法
6453
查看次数

GetDC与BeginPaint性能考虑因素

MSDN和众多帖子都建议在WM_PAINT中使用BeginPaint/EndPaint.我也看到很多地方建议如果在绘画中使用双缓冲,在WM_CREATE初始化DC和mem分配并在WM_PAINT中重用这些句柄更有意义.

例如,使用BeginPaint,我经常看到:

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
MemDC = CreateCompatibleDC(hdc);
bmp = CreateCompatibleBitmap(hdc, width, height);
oldbmp = SelectObject(MemDC,bmp);
g = new Graphics(MemDC);

//do paint on bmp
//blt bmp back to hdc

EndPaint(hWnd, &ps);
DeleteObject(bmp);
g->ReleaseHDC(MemDC);
DeleteDC(MemDC);
delete g;
Run Code Online (Sandbox Code Playgroud)

要保存初始化和拆除,是否可以执行此操作:

case WM_CREATE:
hdc   = GetDC(hWnd);
//create memDC and graphics object references ...
case WM_DESTROY
//delete memDC and graphics object references...
case WM_PAINT
BeginPaint(hWnd, &ps);
//use previously create mem and graphics object to paint 
EndPaint(hWnd, &ps);
Run Code Online (Sandbox Code Playgroud)

因此,我们仅使用EndPaint清除更新区域,但将图形委托给prev创建的对象.

winapi gdi+ gdi wm-paint

3
推荐指数
1
解决办法
1733
查看次数

为什么有时用空矩形调用WM_PAINT?

我正在处理很多绘图.目前我正在使用WM_TIMER来使用InvalidateRect计划绘画.由于某种原因,WM_PAINT经常被调用区域(0,0,0,0),所以基本上是一个空矩形.我试图将其解释为"整个窗口",但之后它似乎会导致性能下降.为什么Windows发送呢?

winapi invalidation wm-paint

3
推荐指数
1
解决办法
211
查看次数

DefWindowProc WinApi的行为

有人可以解释为什么使用DefWindowProc一切正常,但如果我删除它,字符串"Hello windows"出现在屏幕上没有窗口和任何按钮?"UpdateWindow"发送到窗口过程WM_PAINT消息,那么为什么显示文本但是跳过了窗口的创建?

#include <windows.h>

LRESULT CALLBACK proc1 (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Program");
HWND hwnd1;
MSG msg1;
WNDCLASS wndclass1;

wndclass1.style = CS_HREDRAW | CS_VREDRAW;
wndclass1.lpfnWndProc = proc1;
wndclass1.cbClsExtra = 0;
wndclass1.cbWndExtra = 0;
wndclass1.hInstance = hInstance;
wndclass1.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass1.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass1.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclass1.lpszMenuName = NULL;
wndclass1.lpszClassName = szAppName;

RegisterClass (&wndclass1);

hwnd1 = CreateWindow (  szAppName, …
Run Code Online (Sandbox Code Playgroud)

windows winapi wm-paint

2
推荐指数
2
解决办法
2235
查看次数

为什么不手动发送WM_PAINT

我已经读过,我不应该WM_PAINT手动发送,InvalidateRect而是应该打电话但是没有找到任何关于为什么不发送的信息.那为什么不呢?

更新适用InvalidateRect但不适用SendMessage(WM_PAINT)

LRESULT CALLBACK window_proc(HWND wnd, UINT msg, WPARAM w_param, LPARAM l_param)
{
  switch (msg)
  {
    case WM_PAINT:
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(wnd, &ps);

        Polyline(..);

        EndPaint(wnd, &ps);
        return 0;

    case WM_USER:           
        // SendMessage(wnd, WM_PAINT, NULL, NULL);
        // InvalidateRect(wnd, NULL, FALSE);

        return 0;
  }
}
Run Code Online (Sandbox Code Playgroud)

c++ winapi windows-messages wm-paint

2
推荐指数
2
解决办法
8900
查看次数