WinAPI CreateWindow函数创建比set更小的窗口

时间:2016-01-04 00:14:55

标签: c++ winapi screenshot

我的任务是重新创建具有与Windows相似功能的应用程序。截图工具。其中一个是捕获当前活动的窗口的屏幕截图,这是导致我出现问题的原因。一切都几乎完美无缺,然而"剪断"取得一个应用程序比实际应用程序大几个像素,这是因为它的窗口比我设置的略小。

这是我的CreateWindow调用主窗口我测试它:

hwnd = CreateWindow(TEXT("Klasa okien"), TEXT("Screenshot"), WS_OVERLAPPEDWINDOW, 
        10, 10, 350, 400, NULL, NULL, hInstance, NULL);

然后收集关于该窗口大小的信息并继续进行"采取剪辑"功能:

RECT okno;
HWND aktywne = GetForegroundWindow();
GetWindowRect(aktywne, &okno);
CaptureScreen(okno.left, okno.top, okno.right-okno.left, okno.bottom-okno.top);

最后执行这些剪辑的部分功能:

void CaptureScreen(int x, int y, int width, int height)
{
    HDC hDc = CreateCompatibleDC(0);
    HBITMAP hBmp = CreateCompatibleBitmap(GetDC(0), width, height);
    SelectObject(hDc, hBmp);
    BitBlt(hDc, 0, 0, width, height, GetDC(0), x, y, SRCCOPY);
    Bitmap *p_bmp = Bitmap::FromHBITMAP(hBmp, NULL);
...

正如我所说 - 一切都很好,而且正在创建的图片实际上是350x400但是实际窗口的大小似乎是336x393。我还附上了两张照片 - 完美剪辑的照片是由Windows'创建的照片。工具,另一个是我的。

Result of my tool 350x400Result of Windows' snipping tool 336x393

2 个答案:

答案 0 :(得分:7)

此问题是Windows 10特有的,它与Windows 10透明边框有关。例如,如果窗口重新调整边框大小,则左/右/底部的边框大约为7个像素。

如果您正在拍摄屏幕截图,则可能希望排除透明边框。将GetWindowRect替换为:

DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(RECT)); 
//requires at least Windows Vista

GetWindowRect相比,从DwmGetWindowAttribute获得的矩形在左,右和底部可能会缩小约7个像素。

#include "Dwmapi.h"
#pragma comment( lib, "Dwmapi.lib" )
...

RECT rc;
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(RECT));
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;

HDC memdc = CreateCompatibleDC(hdc);
HBITMAP bmp = CreateCompatibleBitmap(hdc, w, h);
SelectObject(memdc, bmp);
BitBlt(memdc, 0, 0, w, h, hdc, rc.left, rc.top, CAPTUREBLT | SRCCOPY);
...

其次,不要使用GetDC(0)(以这种方式),因为它会导致资源泄漏。您必须保存从GetDC获得的句柄并稍后释放。例如:

HWND desktopWnd = GetDesktopWindow();
HDC hdc = GetDC(desktopWnd);
...
ReleaseDC(desktopWnd, hdc);

编辑:
或使用

HDC hdc = GetDC(0);
...
ReleaseDC(0, hdc);

答案 1 :(得分:1)

在CreateWindow()调用AdjustWindowRectEx()之前:

int x = 10;
int y = 10;
int w = 350;
int h = 400;

RECT rect;
rect.left   = x;
rect.top    = y;
rect.right  = x + w;
rect.bottom = y + h;

UINT style = WS_OVERLAPPEDWINDOW;

AdjustWindowRectEx( &rect, style, 0, 0 );

hwnd = CreateWindow(
         TEXT("Klasa okien"), TEXT("Screenshot"), style, 
         rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 
         NULL, NULL, hInstance, NULL
       );

AdjustWindowRectEx