GetDC ReleaseDC CreateCompatibleDC CreateCompatibleBitmap SelectObject DeleteDC DeleteObj

介绍

GetDC 
ReleaseDC 
CreateCompatibleDC   
CreateCompatibleBitmap  
SelectObject  
DeleteDC  
DeleteObject

这些函数是Windows编程中用于图形设备上下文(Device Context, DC)和位图(Bitmap)操作的API函数,它们通常在使用GDI(图形设备接口)进行绘图时会被用到。下面简要解释每个函数的作用:

  1. GetDC(HWND hWnd):

    • 此函数获取指定窗口(hWnd)的设备上下文(DC)。设备上下文是一个包含绘图表面的信息的数据结构,比如屏幕的像素格式、颜色管理能力等。通过DC,应用程序可以在窗口上绘制图形。
  2. ReleaseDC(HWND hWnd, HDC hDC):

    • 释放之前通过GetDC函数获取的指定窗口(hWnd)的设备上下文(hDC)。在使用完DC后,应该调用此函数来释放它,以避免资源泄露。
  3. CreateCompatibleDC(HDC hDC):

    • 创建一个与指定设备上下文(hDC)兼容的内存设备上下文(Memory Device Context, Memory DC)。内存DC允许在内存中绘制图形,然后将这些图形一次性地复制到屏幕或其他设备上,这可以提高绘图性能。
  4. CreateCompatibleBitmap(HDC hDC, int nWidth, int nHeight):

    • 创建一个与指定设备上下文(hDC)兼容的位图。位图是一种图像文件格式,用于存储像素数据。这个函数根据指定的宽度(nWidth)和高度(nHeight)来创建位图。
  5. SelectObject(HDC hDC, HGDIOBJ hObject):

    • 将指定的GDI对象(如位图、画笔、字体等)选入设备上下文(hDC)。这允许你在绘图时使用这个对象。如果成功,函数返回之前被选入DC的对象的句柄;如果失败,返回NULL。
  6. DeleteDC(HDC hDC):

    • 删除指定的设备上下文(hDC)。这通常用于删除通过CreateCompatibleDC等函数创建的内存DC。注意,不能删除通过GetDC获取的DC。
  7. DeleteObject(HGDIOBJ hObject):

    • 删除指定的GDI对象(如位图、画笔、字体等)。在不再需要GDI对象时,应该调用此函数来释放它占用的资源。

这些函数共同支持Windows GDI图形编程,使得开发者能够在Windows应用程序中进行复杂的图形绘制和处理操作。然而,需要注意的是,随着Windows编程技术的不断发展,GDI+和Direct2D等更现代的图形接口已经逐渐取代了GDI,它们提供了更丰富的功能和更好的性能。

扫描二维码关注公众号,回复: 17525630 查看本文章

GetDCReleaseDC 是 Windows 编程中用于图形设备上下文(Device Context, DC)管理的两个非常重要的函数。它们通常与GDI(图形设备接口)一起使用,以在窗口或其他绘图表面上绘制图形。


GetDC

函数原型

HDC GetDC(HWND hWnd);
  • 参数

    • hWnd:指定要获取设备上下文的窗口的句柄。如果此参数为NULL,则函数返回整个屏幕的设备上下文。
  • 返回值

    • 如果函数成功,返回值是指定窗口的设备上下文的句柄。
    • 如果函数失败,返回值是NULL。

作用
GetDC 函数用于获取指定窗口的客户区(即窗口内部,不包括边框、标题栏等)的设备上下文。设备上下文是一个结构体,它包含了设备(如显示器、打印机等)的绘图属性。通过设备上下文,应用程序可以在窗口或屏幕上绘制文本、图形等。

ReleaseDC

函数原型

int ReleaseDC(HWND hWnd, HDC hDC);
  • 参数

    • hWnd:指定设备上下文所属的窗口的句柄。
    • hDC:要释放的设备上下文的句柄。
  • 返回值

    • 如果函数成功,返回值是非零值。
    • 如果函数失败,返回值是零。

作用
ReleaseDC 函数用于释放通过GetDC函数获取的设备上下文。在使用完设备上下文进行绘图后,应该调用ReleaseDC来释放它,以避免资源泄露。如果忘记释放DC,那么窗口可能无法正确重绘,因为DC被占用而无法更新。

示例

// 假设hWnd是一个有效的窗口句柄
HDC hdc = GetDC(hWnd); // 获取窗口的设备上下文
if (hdc != NULL)
{
    // 使用hdc进行绘图操作...

    // 绘图完成后,释放设备上下文
    ReleaseDC(hWnd, hdc);
}

在这个示例中,首先通过GetDC获取窗口的设备上下文hdc。然后,使用hdc进行绘图操作(这里省略了具体的绘图代码)。最后,通过ReleaseDC释放hdc,以确保资源被正确管理。如果GetDC失败(即返回NULL),则不进行任何绘图操作,并且不调用ReleaseDC,因为此时没有有效的DC来释放。然而,在实际编程中,通常会检查GetDC的返回值,并在失败时采取适当的错误处理措施。

示例1

HDC hdcScreen = GetDC(NULL);  
HDC hdcMem = CreateCompatibleDC(hdcScreen);  
HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, 100, 100); // 创建一个100x100的位图  
// 将位图选入内存DC  
HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);  
// 使用 hdcMem 进行绘图操作... 
 
// 恢复旧的GDI对象  
SelectObject(hdcMem, hOld);  
// 清理资源  
DeleteObject(hBitmap);  
DeleteDC(hdcMem);  
ReleaseDC(NULL, hdcScreen);

请注意,上述代码示例中省略了错误处理逻辑,以简化说明。在实际应用中,您应该检查每个GDI函数的返回值,以确保操作成功完成。

示例2

// 假设hWnd是有效的窗口句柄  
HDC hdcScreen = GetDC(NULL);  
HDC hdcMem = CreateCompatibleDC(hdcScreen);  
HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, 200, 100);  
HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);  
  
// 设置文本颜色和背景色  
SetBkColor(hdcMem, RGB(255, 255, 255));  
SetTextColor(hdcMem, RGB(0, 0, 0));  
  
// 选择字体(这里假设已经有一个字体句柄hFont)  
HGDIOBJ hOldFont = SelectObject(hdcMem, hFont);  
  
// 绘制文本  
TextOut(hdcMem, 10, 10, _T("Hello, GDI!"), lstrlen(_T("Hello, GDI!")));  
  
// 恢复旧的GDI对象  
SelectObject(hdcMem, hOldFont);  
SelectObject(hdcMem, hOld);  
  
// 将位图绘制到窗口上(这里假设有一个有效的RECT rect)  
BitBlt(hdcScreen, 100, 100, 200, 100, hdcMem, 0, 0, SRCCOPY);  
  
// 清理资源  
DeleteObject(hBitmap);  
DeleteDC(hdcMem);  
ReleaseDC(NULL, hdcScreen);  
// 注意:这里假设hFont是在其他地方创建的,并且需要单独管理其生命周期

注意1

// 恢复原始位图(如果需要)  
SelectObject(hdcMem, hOldBmp); 

这个是必须调用吗?什么情况下可以不调用?

在Windows GDI编程中,当你使用SelectObject函数将一个新的图形对象(如位图、画笔、笔刷等)选入设备上下文(DC)时,该函数会返回之前被选入该DC的对象的句柄。这个返回的句柄(在上面的例子中为hOldBmp)允许你在将来恢复原来的对象,如果你需要的话。

对于// 恢复原始位图(如果需要)这行代码:

SelectObject(hdcMem, hOldBmp);

是否必须调用取决于你的具体需求。以下是一些情况,说明何时需要调用它,以及何时可以不调用:

需要调用的情况:

  1. 如果你计划在后续操作中使用原始的位图或其他GDI对象:如果你打算在同一个DC上绘制不同的内容,并且需要使用原始的位图或其他GDI对象,那么你应该在不再需要当前选入的GDI对象时将其恢复。

  2. 资源管理:在删除DC之前,恢复原始的GDI对象是一个好习惯,尽管在删除DC时,Windows通常会清理与该DC关联的所有资源。然而,显式地恢复原始对象可以避免潜在的资源泄漏或未定义行为,特别是在复杂的应用程序或库中。

可以不调用的情况:

  1. 如果你知道在删除DC之前不会再使用它:如果你确定在删除DC之前不会再对该DC进行任何绘图操作,那么你可能不需要恢复原始的GDI对象。然而,即使在这种情况下,显式地恢复原始对象仍然是一个好习惯,因为它有助于代码的清晰性和可维护性。

  2. 如果你打算立即删除DC:如果你计划立即删除DC,并且确信没有其他代码或线程会访问它,那么你可以跳过恢复原始GDI对象的步骤。然而,请注意,在多线程环境中,这种假设可能不成立。

总结:

虽然在某些情况下你可能不需要恢复原始的GDI对象,但通常建议总是这样做。它有助于避免资源泄漏、未定义行为,并使代码更加健壮和可维护。在编写GDI代码时,遵循最佳实践,如显式恢复原始GDI对象并在不再需要时删除它们,是一个好习惯。

注意2

如何使用ReleaseDC函数?

ReleaseDC 函数用于释放之前通过 GetDCGetWindowDC 函数获取的设备上下文(Device Context,简称 DC 或 HDC)句柄。当您完成在 DC 上进行绘图或其他操作时,应该调用 ReleaseDC 来释放该 DC,以便 Windows 可以回收与该 DC 相关的资源。

以下是 ReleaseDC 函数的原型和使用示例:

函数原型

int ReleaseDC(HWND hWnd, HDC hDC);
  • hWnd:指向窗口的句柄。如果 DC 是通过 GetDC(NULL) 获得的(即整个屏幕的 DC),则此参数应为 NULL
  • hDC:要释放的设备上下文的句柄。

返回值

如果函数成功,返回值为非零值。如果函数失败,返回值为零。然而,在大多数情况下,您不需要检查 ReleaseDC 的返回值,因为即使 DC 已经被释放或不再有效,调用 ReleaseDC 也不会导致错误。

使用示例

// 假设 hwnd 是您想要在其上绘图的窗口的句柄
HWND hwnd = ...; // 窗口句柄的获取方式取决于您的应用程序

// 获取窗口的 DC
HDC hdc = GetWindowDC(hwnd);
if (hdc != NULL)
{
    
    
    // 使用 hdc 进行绘图操作...

    // 绘图完成后,释放 DC
    ReleaseDC(hwnd, hdc);
}

// 注意:如果 hdc 是 NULL,则通常意味着 GetWindowDC 失败了,
// 在这种情况下,您不需要(也不能)调用 ReleaseDC。

// 如果您想要获取整个屏幕的 DC,可以这样做:
HDC hdcScreen = GetDC(NULL);
if (hdcScreen != NULL)
{
    
    
    // 使用 hdcScreen 在整个屏幕上进行绘图操作(这通常不是个好主意)

    // 完成后,释放屏幕 DC
    ReleaseDC(NULL, hdcScreen);
}

请注意,虽然 ReleaseDC 的返回值可以指示函数是否成功,但在处理 DC 时,通常不需要检查这个返回值,因为即使 DC 已经被释放或不再有效,再次调用 ReleaseDC 也不会导致错误。然而,确保在不再需要 DC 时调用 ReleaseDC 仍然是一个好习惯,以避免资源泄漏。

另外,请注意不要在未成功获取 DC 的情况下调用 ReleaseDC,因为这样做会导致未定义的行为(尽管在某些情况下,如果传递的 DC 句柄实际上是无效的,ReleaseDC 可能会简单地不做任何事情并返回零)。始终检查 GetDCGetWindowDC 的返回值,以确保您有一个有效的 DC 句柄可以释放。

注意3

ReleaseDCDeleteDC的区别?

DeleteDC 的使用场景

DeleteDC函数主要用于删除通过CreateDCCreateCompatibleDCCreateICA等函数创建的DC。这些DC是应用程序创建的,与特定的设备或窗口不直接关联,因此需要通过DeleteDC来显式地删除它们,并释放与之相关的资源。

ReleaseDC 与 DeleteDC 的区别

  • ReleaseDC:用于释放通过GetDCGetWindowDC获取的DC句柄。这些DC是与特定的窗口或屏幕相关联的,并且是由系统管理的。调用ReleaseDC会将DC句柄返回给系统,以便系统可以重新分配和管理这些资源。
  • DeleteDC:用于删除通过CreateDC等函数创建的DC。这些DC是应用程序创建的,并且需要由应用程序显式地删除。调用DeleteDC会销毁DC对象,并释放与之相关的所有资源。

注意事项

  • 不要对通过GetDCGetWindowDC获取的DC句柄调用DeleteDC,也不要对通过CreateDC等函数创建的DC句柄调用ReleaseDC。这样做会导致未定义的行为,可能会损坏系统资源或导致程序崩溃。
  • 在使用DC进行绘图操作时,请确保在不再需要DC时及时释放它,以避免资源泄漏。
  • 如果你在绘图过程中创建了多个DC(例如,使用CreateCompatibleDC创建内存DC进行双缓冲绘图),请确保在绘图完成后删除这些DC,并释放与之相关的资源。

结论

在Windows编程中,释放DC的方法主要有两种:ReleaseDCDeleteDC。选择哪种方法取决于DC的来源和用途。对于通过GetDCGetWindowDC获取的DC,应使用ReleaseDC来释放;对于通过CreateDC等函数创建的DC,应使用DeleteDC来删除。

ReleaseDC和DeleteDC是Windows编程中用于管理图形设备上下文(Device Context, DC)的两个重要函数,它们之间的主要区别体现在它们的作用和使用场景上。


ReleaseDC

作用
ReleaseDC函数用于释放设备上下文环境(DC),它将设备上下文环境与指定的窗口句柄解除关联,并通知操作系统该DC不再被需要,以便它可以被重新分配给其他应用程序或内部使用。这个函数通常与GetDC函数一起使用,后者用于获取设备上下文环境的句柄。

使用场景

  • 当通过GetDC(或GetDCEx)或GetWindowDC函数获取了窗口或屏幕的设备上下文环境后,完成绘图操作后,应使用ReleaseDC来释放该DC。
  • ReleaseDC仅释放那些通过GetDC获得的DC,对通过CreateDC创建的DC没有影响。

注意事项

  • ReleaseDC必须从调用GetDC的同一线程调用。
  • 如果ReleaseDC成功,它会返回非零值;如果失败(例如,传入的句柄无效),则返回零。

DeleteDC

作用
DeleteDC函数用于删除指定的设备上下文环境(DC),包括释放与DC关联的所有资源,并从内存中删除DC对象本身。这个函数通常与CreateDCCreateCompatibleDCCreateICA函数一起使用,后者用于创建设备上下文环境的句柄。

使用场景

  • 当通过CreateDCCreateCompatibleDCCreateICA函数创建设备上下文环境后,不再需要该DC时,应使用DeleteDC来删除它。
  • 注意,如果DC是通过GetDC获得的,则不应使用DeleteDC来删除它,而应该使用ReleaseDC来释放它。

注意事项

  • DeleteDC的返回值表示操作是否成功。如果成功,返回非零值;如果失败(例如,传入的句柄无效),返回零。
  • 在调用DeleteDC之后,应确保没有通过该DC进行任何绘图操作,因为一旦DC被删除,与之关联的所有资源都将被释放,且DC句柄将变得无效。

总结

ReleaseDC DeleteDC
作用 释放设备上下文环境与窗口句柄的关联,通知操作系统该DC不再被需要 删除指定的设备上下文环境,包括释放所有关联资源和删除DC对象本身
使用场景 GetDC(或GetDCEx)或GetWindowDC函数配合使用,释放通过GetDC获取的DC CreateDCCreateCompatibleDCCreateICA函数配合使用,删除通过它们创建的DC
注意事项 必须从调用GetDC的同一线程调用 调用前确保没有通过该DC进行绘图操作
返回值 成功时返回非零值,失败时返回零 成功时返回非零值,失败时返回零

这两个函数都是Windows API的一部分,用于管理图形设备上下文,确保资源得到正确管理和释放,避免资源泄露。在使用时,应根据实际情况选择合适的函数。

猜你喜欢

转载自blog.csdn.net/lijian2017/article/details/141671667