LoginSignup
0
1

More than 5 years have passed since last update.

C++ Builder 10.2 Tokyo > FormShow後に一回だけ実行する > Window Message処理

Last updated at Posted at 2018-05-07
動作環境
RAD Studio 10.2 Tokyo Update 3
秀丸エディタ Version 8.79

関連

FormShow時の処理とFormShow後の処理でWindows 10ではHeightの情報が異なる。

上記においてはFormActivate()を使うことで正しいHeightが得られるようになった。
FormActivate()はフォームのフォーカスが戻ってきたときなどにも実行される。

別の方法としてWindow Messageの方法を実装してみた。

Window Message

上記においてはForm1からForm2へWindow Messageを送信している。

FormShow後の処理では自分自身にWindow Messageを送信する方法が考えられる。

code

  • WM_SHOW_HEIGHTを定義
  • MESSAGE_HANDLER()を定義
  • WMshowHeight()を定義
  • PostMessage(this->Handle, WM_SHOW_HEIGHT, 0, 0);する
Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------

#define WM_SHOW_HEIGHT (WM_APP + 1)

class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TButton *Button1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall FormShow(TObject *Sender);
private:    // ユーザー宣言
    void __fastcall getVisibleWindowSize(TForm *formPtr, TRect *rectPtr);
public:     // ユーザー宣言
    __fastcall TForm1(TComponent* Owner);
    void __fastcall WMshowHeight(TMessage &msg);

BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_SHOW_HEIGHT, TMessage, WMshowHeight);
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
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::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;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TRect arect;

    getVisibleWindowSize(this, &arect);

    int parhei = arect.Bottom - arect.top;
    String msg = IntToStr(parhei) + L" on Button1Click()";
    ShowMessage(msg);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    // FormShow()後に処理するため
    PostMessage(this->Handle, WM_SHOW_HEIGHT, 0, 0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMshowHeight(TMessage &msg)
{
    // ウィンドウHeightの取得
    TRect arect;

    getVisibleWindowSize(this, &arect);

    int parhei = arect.Bottom - arect.top;
    String wrk = IntToStr(parhei) + L" on WMshowHeight()";
    ShowMessage(wrk);
}
//---------------------------------------------------------------------------

実行

  • Windows 10
    • 336 on WMshowHeight()
    • 336 on Button1Click()

同じ値になった。

考察

  • FormActivate()
    • 注意: 様々なソフトにてFormShow()だけを多用している場合、コードを読む人がFormActivate()で処理していることを認識しないかもしれない
    • 利点: Window Messageを使う場合よりもシンプルな構造での実装になる
    • 欠点: static変数の使用
  • Window Message
    • 注意: 別のWindow Messageとかぶらないこと
    • 利点: FormShow()からPostMessage()を実行することで、起動時の認識として判別しやすいかも
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1