作为MFC的相对新手,我看到了很多设备上下文(DC).我隐约明白它与绘图有关,但具体内容在我能找到的任何地方都没有得到很好的解释.创建"兼容的设备上下文"是什么意思,为什么它很重要?SelectObject做了什么,我该如何首先兼容DC?
一旦我们通过GetDC获得上下文设备使用C++编程.如果我们在不调用ReleaseDC的情况下退出程序,可能会发生什么不好的事情?
也许这是一个愚蠢的问题,我不明白为什么我不能在以下代码中创建DC:
HBITMAP COcrDlg::LoadClippedBitmap(LPCTSTR pathName,UINT maxWidth,UINT maxHeight)
{
HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, pathName, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if (!hBmp)
return NULL;
HDC hdc = (HDC)GetDC();
HDC hdcMem = CreateCompatibleDC(hdc);
if (!hdcMem)
{
DWORD err = GetLastError();
}
...
...
...
Run Code Online (Sandbox Code Playgroud)
位图hBmp加载正常,hdc具有有效值.但是对CreateCompatibleDC()的调用返回一个NULL指针.然后,GetLastError()返回0!有谁能猜出这里发生了什么,拜托?
PS:在此之前没有调用内存分配或GDI例程...所以我认为应该排除内存泄漏.
我可以在油漆循环外使用DC吗?我的窗户的DC是否保证永久有效?
我想弄清楚我的控件的设备上下文(DC)有效多长时间.
我知道我可以打电话:
GetDC(hWnd);
Run Code Online (Sandbox Code Playgroud)
获取我的控件窗口的设备上下文,但这是允许的吗?
当Windows向我发送WM_PAINT消息时,我应该调用BeginPaint/EndPaint来正确确认我已经绘制它,并在内部清除无效区域:
BeginPaint(hWnd, {out}paintStruct);
try
//Do my painting
finally
EndPaint(hWnd, paintStruct);
end;
Run Code Online (Sandbox Code Playgroud)
但是调用BeginPaint也会在PAINTSTRUCT结构中返回一个DC.这是我应该画的DC .
我在文档中找不到任何说明BeginPaint()返回的DC与我从GetDC()获得的DC相同的内容.
特别是现在,在桌面组合的时代,我在BeginPaint之外获得的DC上绘画是否有效?
在涂装周期中,似乎有两种方法可以让DC涂漆:
dc = GetDC(hWnd);
调用BeginPaint(&PAINTSTRUCT);
还有第三种方法,但它似乎是我开发的Borland Delphi的一个错误.
在WM_PAINT处理期间,Delphi认为wParam是一个DC,并继续绘制它.而MSDN表示WM_PAINT消息的wParam未使用.
我的真正目标是尝试将持久的GDI + Graphics对象与HDC保持一致,这样我就可以使用一些更好的GDI +功能,这些功能依赖于持久性DC.
在WM_PAINT消息处理期间,我想将一个GDI +图像绘制到画布上.以下nieve版本非常慢:
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);
}
Run Code Online (Sandbox Code Playgroud)
GDI包含性能更快的位图,即CachedBitmap.但是不假思索地使用它不会带来任何性能优势
WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(m_hwnd, ps);
Graphics g = new Graphics(ps.hdc);
CachedBitmap bm = new …
Run Code Online (Sandbox Code Playgroud) 背景
我编写了一个函数,它根据与给定设备上下文关联的位图创建自定义光标.我使用它来创建拖拽光标,显示为"撕下" - 有点像它们在"Trello"中使用.
我一直在使用该函数一段时间没有问题,但当我使用它与新的树组件我正在努力它开始创建部分空白游标.
我已经验证了Delphi 2010和Delphi Berlin都出现了这个问题,并且我也验证了它在Windows 7和Windows 10中都被破坏了.
这是一张显示光标应该是什么样子的照片(对不起 - 找不到快速浏览光标的方法):
而且当它部分空白时它看起来像是什么(好吧,它不仅仅是部分空白 - 它实际上是不可见的):
故障排除
在我发现故障排除之后,如果在调用GetDragCursor 之前将PNG图像写入与DC关联的位图,则光标会混乱.
这是我能想到的最简单的代码,用于演示问题:
包含两个TPaintBox组件的表单:MyPaintBoxWorks和MyPaintBoxBroken.
为了使其易于阅读(我希望),我已经排除了所有错误和资源处理.这对问题没有影响.为了使其工作,您需要访问Png图像.任何png图像都可以.然后更新代码以加载图像.
uses
Types,
pngimage;
//////////////////////////////////////////////////////////////////////
procedure TMyForm.FormPaint(Sender: TObject);
begin
MyPaintBoxWorks.Canvas.Brush.Color := clGreen;
MyPaintBoxWorks.Canvas.Rectangle( 0, 0,
MyPaintBoxWorks.Width, MyPaintBoxWorks.Height );
MyPaintBoxBroken.Canvas.Brush.Color := clRed;
MyPaintBoxBroken.Canvas.Rectangle( 0, 0,
MyPaintBoxBroken.Width, MyPaintBoxBroken.Height );
end;
function GetDragCursor( Handle: HDC;
Width, Height: integer;
CursorX, CursorY: integer ): TCursor; forward; …
Run Code Online (Sandbox Code Playgroud) 我正在调用Win32 DrawText
函数将一些文本输出到设备上下文中.文本很长,很好地包装在第二行.问题是我需要减少线之间的空间(我猜减少线高?).关于如何做到这一点的任何想法?
我只会打DrawText
两次电话(每一行一次)但是我必须做自己的自动换行.
还有其他方法吗?
谢谢
在这段代码中,我希望有一个调用ReleaseDC
发生MyCanvas.Free
,但这段代码运行正常,怎么样?
TCanvas自己的DC会发生什么?
var GlobalDC: THandle;
procedure TForm1.FormCreate(Sender: TObject);
begin
GlobalDC:= GetDC(0);
end;
function LoopMeOften(const X, Y: Integer): TColor;
var
MyCanvas: TCanvas;
begin
MyCanvas := TCanvas.Create;
MyCanvas.Handle := GlobalDC;
Result := GetPixel(MyCanvas.Handle, X, Y);
MyCanvas.Free;
end;
Run Code Online (Sandbox Code Playgroud) 两个设备上下文(DC)可以共享一个GDI对象,例如画笔还是笔?
另外一个绘图问题MFC/GDI大师那里...... :-)
我正在使用MFC,我正在使用CDC对象进行绘图.这很好.
但是现在我想绘制一个带圆角的矩形,这条线宽几个像素.但我不希望任何填充发生!有一种方法CDC :: RoundRect - 我只是设置了我想要的笔,并用这支笔得到一个漂亮的圆角矩形.但CDC :: RoundRect也用当前画笔填充矩形.
有没有办法画线,没有填充?我还没找到任何其他方法?或者我可以创建某种"空刷",它不会改变矩形中间的内容吗?
我非常感谢你的一些好建议!
/来自瑞典的安德斯
我需要它使用GDI函数处理RGB24数据(特别是StretchBlt()非常快)我不能使用CreateCompatibleDC(),因为它只能用其他DC的颜色深度创建内存DC.通常它用于屏幕DC(通过传输NULL指针到功能),通常屏幕的颜色深度为32.此外我不能依赖它,'因为如果屏幕设置被更改,我的应用程序可能无法正常工作.
所以我需要一些方法来创建具有特定特定颜色深度的内存DC.到目前为止,我发现使用CreateDC()函数只有一种方法,但它需要许多特定于设备的参数,对我来说似乎有点不可靠.此外,有太多的字段需要填充适当的值来调用CreateDC().
是否有一些更简单的方法来创建特定的内存DC而不依赖于某些设备?或者即使创建24 bpp的内存DC?
PS我需要一些快速的图形.我已经尝试手动将alpha通道添加到位图以使用它兼容屏幕32bpp内存DC并且它已经解决了,但是太慢了.正如我上面所说,我不能依赖可以更改的屏幕设置.
有没有办法让窗口处理窗口拥有win32 DC?或者任何其他可能对识别窗口有用的信息,如DC宽度和高度?