動作環境
RAD Studio 10.2 Tokyo Update 3
C++ Builder XE4
秀丸エディタ Version 8.79
Windows 7 Pro (32bit)
Windows 8.1 Pro (64bit)
Windows 10 v1709 (64bit)
関連
Windows 7, 8.1, 10でのフォームHeight, Width取得
Windows 10からinvisible borderが導入されたため、Windows 7, 8.1, 10上でのソフト動作(位置調整)が変わってしまう。
それを避けるためgetVisibleWindowSize()を実装したが、様々なフォームから使用するにはソース分離する方がいいだろう。
下記においてソース分離した。
code
UtilFormSize_noInvisibleBorder.h
//---------------------------------------------------------------------------
#ifndef UtilFormSize_noInvisibleBorderH
#define UtilFormSize_noInvisibleBorderH
//---------------------------------------------------------------------------
/*
Windows 10から導入された「Invisible border」。
Windows 7, 8.1, 10で同じ位置調整処理を使えるようにするため、Invisible borderを含まない
サイズを返す関数を用意した。
*/
class CUtilFormSize_noInvisibleBorder
{
private:
static void __fastcall getVisibleWindowSize(TForm *formPtr, TRect *rectPtr);
public:
static int __fastcall GetHeight(TForm *formPtr);
static int __fastcall GetWidth(TForm *formPtr);
// テスト関数
static void __fastcall Test_showHeightAndWidth(TForm *formPtr);
};
#endif
UtilFormSize_noInvisibleBorder.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "UtilFormSize_noInvisibleBorder.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
/*
v0.1 2018/05/07
- Test_showHeightAndWidth()追加
- GetWidth()追加
- GetHeight()追加
- getVisibleWindowSize()追加
*/
//---------------------------------------------------------------------------
// private関数
//
/*static*/void __fastcall CUtilFormSize_noInvisibleBorder::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)の方を返す
//
// !!!ただしWindows 10の場合、FormShow時には正しい値を返さない!!!
// FormShow後に実行すること
rectPtr->left = arect_inv.left;
rectPtr->top = arect_inv.top;
rectPtr->right = arect_inv.right;
rectPtr->bottom = arect_inv.bottom;
}
//---------------------------------------------------------------------------
// public関数
//
/*static*/ int __fastcall CUtilFormSize_noInvisibleBorder::GetHeight(TForm *formPtr)
{
// !!!Windows 10の場合、FormShow時には正しい値を返さない!!!
// FormShow後に実行すること
if (formPtr == NULL) {
return 0; // error
}
TRect arect;
getVisibleWindowSize(formPtr, &arect);
return arect.bottom - arect.top;
}
/*static*/ int __fastcall CUtilFormSize_noInvisibleBorder::GetWidth(TForm *formPtr)
{
// !!!Windows 10の場合、FormShow時には正しい値を返さない!!!
// FormShow後に実行すること
if (formPtr == NULL) {
return 0; // error
}
TRect arect;
getVisibleWindowSize(formPtr, &arect);
return arect.right - arect.left;
}
//---------------------------------------------------------------------------
// テスト関数
//
/*static*/ void __fastcall CUtilFormSize_noInvisibleBorder::Test_showHeightAndWidth(TForm *formPtr)
{
if (formPtr == NULL) {
return; // error
}
int hei = CUtilFormSize_noInvisibleBorder::GetHeight(formPtr);
int wid = CUtilFormSize_noInvisibleBorder::GetWidth(formPtr);
String msg = String().sprintf(L"%d x %d", hei, wid);
ShowMessage(msg);
}
使用例
Test_showHeightAndWidth()の実装を参考にする。
注意事項
Windows 10においてはFormShow時にフォームのHeight, Widthが正しく取得できない。
FormShow後にHeightとWidthを取得すると良い (下記参照)。