我允许使用直流之外的一个油漆循环?是我的窗口的DC保证是有效的永远?

我试图找出多久我控制的设备上下文(直流)是有效的。

我知道,我可以叫:

GetDC(hWnd);

要获得设备的背景下我控制的窗口,但是允许的?

当窗户发送我一个WM_PAINT消息,我应该呼叫 BeginPaint/EndPaint 要正确地确认我已经画,并为内部清除无效的区域:

BeginPaint(hWnd, {out}paintStruct);
try
   //Do my painting
finally
   EndPaint(hWnd, paintStruct);
end;

但呼吁BeginPaint也返回我一直流内PAINTSTRUCT结构。这是DC我 应该 是的绘画上。

我找不到任何东西在文件中说,DC返回的BeginPaint()是相同的直流电,我会得到从GetDC().

尤其是现在,在桌面上组成,它是有效的画上一直流,我获得外部的BeginPaint?

似乎有2种方式我可以一直上的油漆过的油漆周期:

  1. dc= GetDC(hWnd);

  2. BeginPaint(&paintStruct);

有一个第3方式,但它似乎是一个错误Borland德尔菲,我的发展。

WM_PAINT 处理,Delphi认为,包含一直流,并进行油漆。而MSDN说,包含一个WM_PAINT消息是未使用。

为什么

我的真正目标 是要尽量保持一个持久的GDI+形对象的 对一个裂,所以,我可以用一些更好的执行功能的GDI+那取决于具有持久性。

在WM_PAINT消息处理我想画一个GDI+图像的画布上。下雪山的版本是非常缓慢:

WM_PAINT:
{
   PAINTSTRUCT ps;
   BeginPaint(m_hwnd, ps);
   Graphics g = new Graphics(ps.hdc);
   g.DrawImage(m_someBitmap, 0, 0);
   g.Destroy();
   EndPaint(h_hwnd, ps);
}

GDI包含一个执行速度更快的位,CachedBitmap.但是,使用它没有思想没有给出性能的好处:

WM_PAINT:
{
   PAINTSTRUCT ps;
   BeginPaint(m_hwnd, ps);

   Graphics g = new Graphics(ps.hdc);
   CachedBitmap bm = new CachedBitmap(m_someBitmap, g);
   g.DrawCachedBitmap(m_bm, 0, 0);
   bm.Destroy();
   g.Destroy();
   EndPaint(h_hwnd, ps);
}

该性能的收益来自创造CachedBitmap一次,所以在程序初始化:

m_graphics = new Graphics(GetDC(m_hwnd));
m_cachedBitmap = new CachedBitmap(b_someBitmap, m_graphcis);

现在油漆周期:

WM_PAINT:
{
   PAINTSTRUCT ps;
   BeginPaint(m_hwnd, ps);
   m_graphics.DrawCachedBitmap(m_cachedBitmap, 0, 0);
   EndPaint(h_hwnd, ps);
}        

除了现在我相信,DC我后获得程序initializtion将是相同的DC为我的窗口,只要应用程序正在运行。这意味着它的生存通过:

  • 快用户的开关
  • 组成启用/停用
  • 主题交换
  • 主题是禁止

我什么也找不到在MSDN,保证同DC将用于一个特别窗口,只要的窗口存在。

注: 我不是采用双缓冲, 因为我想要的是一个很好的开发,做正确的事情.有时那意味着你的双缓冲坏。

有帮助吗?

解决方案

也有例外,但在一般情况下,你可能会得到不同的DC你每次呼叫 GetDCBeginPaint.因此你不应该试图保存的状态的直流电。(如果你必须做这个的性能、有特殊DCs你可以创建一类的窗户或一个特别窗口的实例,但它不像,你真的需要或不想要的。)

大部分时间,但是,这些DCs将是兼容的。他们将代表相同的图形方式,因此兼容位应工作,甚至如果你得到一个不同的。

有窗户的消息告诉你当形模式的变化,喜欢 WM_DISPLAYCHANGEWM_PALETTECHANGED.你可以听听这些,并重缓存图。由于这些都是罕见的事件,您不必担心,有关性能的影响的重建你的缓位在这一点上。

你还可以得到通知,如主题的变化。那些不改变形模式--他们是较高级别的概念--所以你的缓位仍然应该是兼容的任何DC你得到的。但如果你想改变位当主题的变化,可以监听 WM_THEMECHANGED 为好。

其他提示

只有这样,我知道的可能(或不可能)来做什么你要找的是建立窗口 CS_OWNDC 类风格。

什么,不会被分配一个独特的设备方面为每个窗口的类。

编辑

从联MSDN文章:

一个装置上下文中是一个特殊的设置 值应用的使用 图在客户区,他们的 窗户。该系统需要一个装置 下文对每个窗口在显示器上 但允许一些灵活性,在怎样的 系统存储和把那设备 上下文。

如果没有设备方面的风格是 明确给出的,该系统的假设 每一个窗口使用的一个装置上下文 从一个游泳池的情况下 维持通过系统。在这样 情况中,每个窗口,必须检索和 初始化装置的上下文之前 绘画和免费的后画。

为了避免检索装置的上下文 每次它需要油漆内 窗口,一个应用程序可以指定 CS_OWNDC式的窗口类。这类式的指示系统 创建一个私人的设备上下文, 是,分配一个独特的设备 下文对每一窗口的类。该应用程序需要的只是检索的 下一次,然后使用它的所有 随后的绘画。

Windows95/98/Me:虽然 CS_OWNDC式是方便,使用它 小心,因为每个装置的上下文 使用的一个重要部分64K GDI 堆。

也许这个例子将说明使用的CS_OWNDC更好:

#include <windows.h>

static TCHAR ClassName[] = TEXT("BitmapWindow");
static TCHAR WindowTitle[] = TEXT("Bitmap Window");

HDC m_hDC;
HWND m_hWnd;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static PAINTSTRUCT ps;

    switch (msg)
    {
    case WM_PAINT:
        {
            BeginPaint(hWnd, &ps);

            if (ps.hdc == m_hDC)
                MessageBox(NULL, L"ps.hdc == m_hDC", WindowTitle, MB_OK);
            else
                MessageBox(NULL, L"ps.hdc != m_hDC", WindowTitle, MB_OK);

            if (ps.hdc == GetDC(hWnd))
                MessageBox(NULL, L"ps.hdc == GetDC(hWnd)", WindowTitle, MB_OK);
            else
                MessageBox(NULL, L"ps.hdc != GetDC(hWnd)", WindowTitle, MB_OK);

            RECT r;
            SetRect(&r, 10, 10, 50, 50);
            FillRect(m_hDC, &r, (HBRUSH) GetStockObject( BLACK_BRUSH ));

            EndPaint(hWnd, &ps);
            return 0;
        }
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{   
    WNDCLASSEX wcex;

    wcex.cbClsExtra = 0;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.cbWndExtra = 0;
    wcex.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
    wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wcex.hIconSm = NULL;
    wcex.hInstance = hInstance;
    wcex.lpfnWndProc = WndProc;
    wcex.lpszClassName = ClassName;
    wcex.lpszMenuName = NULL;
    wcex.style = CS_OWNDC;

    if (!RegisterClassEx(&wcex))
        return 0;

    DWORD dwExStyle = 0;
    DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;

    m_hWnd = CreateWindowEx(dwExStyle, ClassName, WindowTitle, dwStyle, 0, 0, 300, 300, NULL, NULL, hInstance, NULL);

    if (!m_hWnd)
        return 0;

    m_hDC = GetDC(m_hWnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

该CS_OWNDC标志 要混淆CS_CLASSDC标志,其中:

分配一个装置上下文中可以共享通过所有的窗户类。因为窗口类别处理具体的,能够对多线程的一个应用程序,以创建一个窗口的同类。它也可能是对的线以尝试使用的设备方面同时进行。当发生这种情况,该系统允许只有一线成功地完成了其绘图操作。

如果一切都失败只是 重建 该CachedBitmap.

当你建造一个CachedBitmap对象,就必须通过该地址的图象的要构造。如果关联的屏幕与图形象具有其位深度改变后的缓位是构建,然后DrawCachedBitmap方法会失败,应该重新构建的高速缓存图。或者,也可以显示改变通知消息,并重建的高速缓存位。

我不是说CS_OWNDC是完美的解决方案,但它 一步步走向一个更好的解决方案。

编辑

样品的程序似乎保留相同的DC在屏幕决议/位深度的改变测试与CS_OWNDC标志,但是,当这标志已被删除,直流是不同的(窗口7 64位的最终)(应该 工作同过differn操作系统版本...虽然它不会伤害到试验)。

Edit2

这个例子不叫GetUpdateRect检查窗户的需要绘期间WM_PAINT.这是一个错误。

你可以画到哪窗口dc高兴你。他们都是有效的。一个窗口并不只是一直流,可以代表它的时间。所以你每次呼叫GetDC和BeginPaint境内这样做,你会得到一个新的、独特的直流电,尽管如此表示同样显示区域。只是ReleaseDC(或EndPaint)当你完成后他们。在Windows3.1设备情况下是有限的,或者非常昂贵的系统资源,因此应鼓励永远不会抓住他们,但对它们进行检索,从GetDC缓存。现在它完全可以接受的创造dc在窗口的设立和高速缓存这对生活的窗口。

唯一的"问题",在处理 WM_PAINT, dc返回的BeginPaint会被剪辑无效rect,并保存一个不会。


我不是明白你正在尝试实现与gdiplus.通常,如果对象是...选择成直流长的一段时间,直流是一个存储器,直流电,没有一个窗口。


每次GetDC是叫你会得到一个新的裂代表一个独特的设备方面有其自己的国家。因此,对象背景的颜色,案文的模式等等。设置在一个DC不会影响该国的另一个DC检索的通过不同的称呼来GetDC或BeginPaint.

该系统不能随意无效HDCs检索到通过客户,并且实际上做了大量工作的背景,以确保HDCs检索之前,显示方式开关、继续的功能。甚至改变位深度,这在技术上使dc是不相容的,将不会以任何方式阻止应用程序继续使用一个跳到位图传送.

这就是说,这是明智的,看着至少对于窗口,释放任何缓存DCs和设备位图,并重新创造他们。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top