C++ Builder XE4 > Windows 7, 8.1, 10 のウィンドウサイズ情報を見る

```txt:実装環境
C++ Builder XE4
```

### 関連

- [winAppDev > Link > Windows 10 > invisible border > 1px: visible, 8px: invisible](https://qiita.com/7of9/items/cca6839d914ce52897d9)

### ウィンドウサイズを知る

Windows 10特有の「invisible border」。

Windows 7, 8.1, 10で同じようにウィンドウ配置するためには、invisible borderを含まないvisibleなウィンドウサイズ情報を知る必要がある。

[WPF and WIndows 10. Invisible border around windows?](https://stackoverflow.com/questions/35259756/wpf-and-windows-10-invisible-border-around-windows)

> answered May 18 '16 at 23:59
mikew

> You can get the offests by using a combination of the normal `GetWindowRect` function and the use of the `DwmGetWindowAttribute` function, together with the `DWMWA_EXTENDED_FRAME_BOUNDS` parameter.

上記の関数を使ってウィンドウ情報を調べてみる。

### code

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TRect arect_inv;
    RECT arect_nrm;

    HWND hwnd1 = this->Handle;
    HWND hwnd2 = this->Handle;

    GetWindowRect(hwnd1, &arect_nrm);
    DwmGetWindowAttribute(hwnd2, DWMWA_EXTENDED_FRAME_BOUNDS, &arect_inv, sizeof(TRect));

	String msg;
	msg = String().sprintf(L"GetWindowRect: top:%d, bottom:%d, left:%d, right:%d",
		arect_nrm.top, arect_nrm.bottom, arect_nrm.left, arect_nrm.right);
	msg += L"\r\n";
	msg += String().sprintf(L"DwmGetWindowAttribute: top:%d, bottom:%d, left:%d, right:%d",
		arect_inv.top, arect_inv.bottom, arect_inv.left, arect_inv.right);

    ShowMessage(msg);
}
//---------------------------------------------------------------------------
```

## 実行結果

### Windows 7

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/8ad73bff-ccef-72b5-fba2-7906ef3a00d5.png)

### Windows 8.1

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/540c943e-b9f3-a801-dbae-20fb090fdb63.png)

### Windows 10

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/586b60b8-5ed2-9dac-6301-87a54b23fbd4.png)

## 知見

- Windows 7では`DwmGetWindowAttribute()`が0を返す
- Windows 8.1と10では`DwmGetWindowAttribute()`からvisibleのウィンドウサイズが得られそう


### code > OSによらずvisible ウィンドウサイズを得る

```Unit1.c
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TRect arect;

	GetVisibleWindowSize(this, &arect);

	int width = arect.bottom - arect.top;
	int height = arect.right - arect.left;
	String msg = String().sprintf(L"left:%d top:%d W:%d H:%d",
		arect.left, arect.top, width, height);

	ShowMessage(msg);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::GetVisibleWindowSize(TForm *formPtr, TRect *rectPtr)
{
	TRect arect_inv;
	RECT arect_nrm;

	if (formPtr == NULL || rectPtr == NULL) {
		return; // error
	}

	GetWindowRect(formPtr->Handle, &arect_nrm); // (1)
	DwmGetWindowAttribute(formPtr->Handle, DWMWA_EXTENDED_FRAME_BOUNDS, &arect_inv, sizeof(TRect)); // (2)

	// for Windows 7
	if (arect_inv.left == 0 && arect_inv.top == 0 && arect_inv.Bottom == 0 && arect_inv.right == 0) {
		// DwmGetWindowAttribute()が0を返すためGetWindowRect()の結果を使う
		rectPtr->left = arect_nrm.left;
		rectPtr->top = arect_nrm.top;
		rectPtr->right = arect_nrm.right;
		rectPtr->bottom = arect_nrm.bottom;
		return;
	}

	// for Windows 8.1, Windows 10
	//   Windows 8.1では(1)と(2)は同じ定義
	//   Windows 10ではinvisible borderにより(1)と(2)の結果が異なる
	//   invisible borderのサイズを含まない(2)の方を返す
	rectPtr->left = arect_inv.left;
	rectPtr->top = arect_inv.top;
	rectPtr->right = arect_inv.right;
	rectPtr->bottom = arect_inv.bottom;
}
```