プログラミングのメモ帳(C/C++/HSP)

日々のプログラミングで気づいた点や小技集を紹介します。(Windows 10/XP/Vista、VC2017、HSP)

ウインドウの移動範囲を制御

2011年12月08日 03時03分00秒 | ウインドウ関連

ウインドウの移動範囲を制御する方法は次の通りです。(戻る)

  1. WM_ENTERSIZEMOVE メッセージで移動範囲のクリッピング領域を設定(ClipCursor)
  2. WM_MOVING メッセージで移動中のウインドウ位置を制御(funcMoveClipping)
  3. WM_EXITSIZEMOVE メッセージで移動範囲のクリッピング領域を解除(ClipCursor)

今回のサンプルでは、ウインドウがデスクトップの外に絶対に移動できなくなります。
時計ソフトなどのミニソフトなどの移動範囲を制御したいときに使えます。

プロトタイプ宣言

BOOL SystemParametersInfo(
    UINT    uiAction,           // 取得または設定するべきシステムパラメータ
    UINT    uiParam,            // 実施するべき操作によって異なる
    PVOID   pvParam,            // 実施するべき操作によって異なる
    UINT    fWinIni             // ユーザープロファイルの更新オプション
);

BOOL ClipCursor(
    CONST RECT*     lpRect      // 長方形領域
);

構造体

typedef struct _RECT {
    LONG    left;       // 左上隅のX座標
    LONG    top;        // 左上隅のY座標
    LONG    right;      // 右下隅のX座標
    LONG    bottom;     // 右下隅のY座標
} RECT, *LPRECT;

サンプル

// break 付きのキーワード
#define CASE        break;case
#define DEFAULT     break;default

// ワークエリア領域の取得
#define GetMonitorRect(rc)  SystemParametersInfo(SPI_GETWORKAREA,0,rc,0)

// ウインドウのクリッピング処理
VOID funcMoveClipping( LPRECT rcDesktop, LPRECT rcWindow )
{
    if ( rcWindow->left < rcDesktop->left ){
        rcWindow->right     = (rcDesktop->left + (rcWindow->right - rcWindow->left));
        rcWindow->left      = (rcDesktop->left);
    }
    if ( rcWindow->right > rcDesktop->right ){
        rcWindow->left      = (rcDesktop->right - (rcWindow->right - rcWindow->left));
        rcWindow->right     = (rcDesktop->right);
    }
    if ( rcWindow->top < rcDesktop->top ){
        rcWindow->bottom    = (rcDesktop->top + (rcWindow->bottom - rcWindow->top));
        rcWindow->top       = (rcDesktop->top);
    }
    if ( rcWindow->bottom > rcDesktop->bottom ){
        rcWindow->top       = (rcDesktop->bottom - (rcWindow->bottom - rcWindow->top));
        rcWindow->bottom    = (rcDesktop->bottom);
    }
}

// ウインドウの移動範囲を制御
BOOL WindowMoveClip( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    static RECT rc;
    
    switch ( uMsg ){
        CASE WM_ENTERSIZEMOVE:      GetMonitorRect( &rc );
                                    ClipCursor( &rc );
        CASE WM_EXITSIZEMOVE:       ClipCursor( NULL );
        CASE WM_MOVING:             funcMoveClipping( &rc, (LPRECT)lParam );
        DEFAULT:                    return FALSE;
    }
    UNREFERENCED_PARAMETER( wParam );
    return TRUE;
}

使い方1(ウインドウ・プロシージャ)

// break 付きのキーワード
#define CASE        break;case
#define DEFAULT     break;default

// ウインドウ・プロシージャの関数
LRESULT CALLBACK mainWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    if ( WindowMoveClip(hWnd,uMsg,wParam,lParam) ){
        return 0;
    }
    switch ( uMsg ){
        CASE WM_CLOSE:      DestroyWindow( hWnd );
        CASE WM_DESTROY:    PostQuitMessage( 0 );
        DEFAULT:            return DefWindowProc( hWnd, uMsg, wParam, lParam );
    }
    return 0;
}
  • ウインドウ・プロシージャで使うときは、WindowMoveClip 関数が実行されたら 0 を返します。
  • 上記の使い方でウインドウを移動するとウインドウはデスクトップの外に移動できなくなります。
  • なお、WindowMoveClip 関数を実行しなければ通常と同じくデスクトップの外にもウインドウが移動可能。

使い方2(ダイアログ・プロシージャ)

// break 付きのキーワード
#define CASE        break;case
#define DEFAULT     break;default

// ダイアログ・プロシージャの関数
BOOL CALLBACK mainDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    if ( WindowMoveClip(hDlg,uMsg,wParam,lParam) ){
        return TRUE;
    }
    switch ( uMsg ){
        CASE WM_CLOSE:      EndDialog( hDlg, IDOK );
        DEFAULT:            return FALSE;
    }
    return TRUE;
}
  • ダイアログ・プロシージャで使うときは、WindowMoveClip 関数が実行されたら TRUE を返します。
  • 上記の使い方でウインドウを移動するとウインドウはデスクトップの外に移動できなくなります。
  • なお、WindowMoveClip 関数を実行しなければ通常と同じくデスクトップの外にもウインドウが移動可能。

関連記事



コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 仮想キーの状態を取得 | トップ | ウインドウの移動位置を固定 »
最新の画像もっと見る

コメントを投稿

ウインドウ関連」カテゴリの最新記事