一回も披露したことのない豆知識

ウィンドウのサイズ変更について質問です。

ウィンドウをサイズ変更する際に、マウスで指定数動いた時だけ
サイズ変更するようにしたいのですが、何か方法はあるのでしょうか?

ちなみに、
拡張ウィンドウスタイルは、
WS_EX_TOOLWINDOW | WS_EX_LAYERED | WS_EX_ACCEPTFILES
ウィンドウスタイルは、
WS_POPUPWINDOW | WS_CLIPCHILDREN
です。

「WS_THICKFRAME」を使用してやろうとしたのですが出来ませんでした。
何か方法があるのかもしれませんが。

開発環境
XP
Visual Studio 2005
C、C++でWindowsAPIを使用しています。

A 回答 (5件)

 こんにちは。

御礼頂きました。
 予期せぬ事態がおきるとWM_CANCELMODEが送られてくるので、此処でキャプチャが外れてしまった時の処理をします。
 又、マウスがリサイズ領域に当たった時のカーソル変更等も自力で行う必要があります(今回此れは省略しています)。
 大体こんな感じです。

#include<windows.h>
#include<commctrl.h>
#include<tchar.h>

#pragma comment(lib, "comctl32.lib")

const DWORD WS_EX_LAYERED = 0x80000;

static LPARAM s_hitState = HTNOWHERE;

//ウィンドウクラス登録
static ATOM Regist(LPCTSTR szClassName, WNDPROC wndProc)
{
WNDCLASSEX wndclass = {sizeof(wndclass)};
wndclass.hCursor= ::LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon= NULL;
wndclass.lpszMenuName= NULL;
wndclass.lpszClassName= szClassName;
wndclass.hbrBackground= (HBRUSH)::GetStockObject(WHITE_BRUSH);
wndclass.hInstance= ::GetModuleHandle(NULL);
wndclass.style= 0;
wndclass.lpfnWndProc= wndProc;
wndclass.cbClsExtra= 0;
wndclass.cbWndExtra= 0;
return ::RegisterClassEx(&wndclass);
}

//ウィンドウを作成して開く
static HWND OpenWindow(LPCTSTR szClassName, LPCTSTR szTitleName, INT w, INT h, LPVOID pData)
{
HINSTANCE hInst = ::GetModuleHandle(NULL);

HWND hWnd = ::CreateWindowEx(WS_EX_TOOLWINDOW | /*WS_EX_LAYERED |*/ WS_EX_ACCEPTFILES, szClassName, szTitleName,
WS_POPUPWINDOW | WS_CLIPCHILDREN,// | WS_THICKFRAME,
CW_USEDEFAULT,CW_USEDEFAULT, w, h,
NULL, NULL,
hInst, pData);
return hWnd;
}

static LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}

static LRESULT OnClose(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
::DestroyWindow(hWnd);
return 0;
}

static LRESULT OnNCDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
::PostQuitMessage(0);
return 0;
}

static LRESULT OnCancelMode(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
s_hitState = HTNOWHERE;
return 0;
}

static LRESULT OnLButtonDown(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//リサイズ枠と見なす幅
LONG ResizeEdge = 4;

//マウス位置を取る
POINT pt;
::GetCursorPos(&pt);

//ウィンドウ位置を取る
RECT rc = {0};
::GetWindowRect(hWnd, &rc);

//リサイズ枠の位置ではないと見なす
if(pt.x < rc.right - ResizeEdge && pt.y < rc.bottom - ResizeEdge)
return 0;

if(pt.x >= rc.right - ResizeEdge && pt.y >= rc.bottom - ResizeEdge)
{
s_hitState = HTBOTTOMRIGHT;
}
else if(pt.x >= rc.right - ResizeEdge)
{
s_hitState = HTRIGHT;
}
else if(pt.y >= rc.bottom - ResizeEdge)
{
s_hitState = HTBOTTOM;
}

//キャプチャをする
::SetCapture(hWnd);
return 0;
}

static LRESULT OnLButtonUp(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//キャプチャを解く
s_hitState = HTNOWHERE;
::ReleaseCapture();
return 0;
}

static LRESULT OnMouseMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//移動量
LONG lPct = 16;

//キャプチャされてないので引き返す
if(s_hitState == HTNOWHERE)
return 0;

POINT pt;
::GetCursorPos(&pt);

RECT rc = {0};
::GetWindowRect(hWnd, &rc);

switch(s_hitState)
{
case HTRIGHT:
case HTBOTTOMRIGHT:
//横に対して
if(((pt.x - rc.right) % lPct) == 0)
{
::SetWindowPos(hWnd, NULL, 0, 0, pt.x - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
}
};

switch(s_hitState)
{
case HTBOTTOM:
case HTBOTTOMRIGHT:
//縦に対して
if(((pt.y - rc.bottom) % lPct) == 0)
{
::SetWindowPos(hWnd, NULL, 0, 0, rc.right - rc.left, pt.y - rc.top, SWP_NOMOVE | SWP_NOZORDER);
}
};

return 0;
}

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:::OnCreate(hWnd, uMsg, wParam, lParam); break;
case WM_CLOSE:::OnClose(hWnd, uMsg, wParam, lParam); break;
case WM_NCDESTROY:::OnNCDestroy(hWnd, uMsg, wParam, lParam); break;
case WM_LBUTTONDOWN :::OnLButtonDown(hWnd, uMsg, wParam, lParam); break;
case WM_LBUTTONUP:::OnLButtonUp(hWnd, uMsg, wParam, lParam); break;
case WM_MOUSEMOVE:::OnMouseMove(hWnd, uMsg, wParam, lParam); break;
case WM_CANCELMODE:::OnCancelMode(hWnd, uMsg, wParam, lParam); break;
}

return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPSTR lpCmdLine, int nShowCmd)
{
const TCHAR tstrClassName[] = TEXT("test resize frame");
const TCHAR tstrTitleName[] = TEXT("title");
MSG msg;

::InitCommonControls();

//ウィンドウクラスの登録
::Regist(tstrClassName, &::WndProc);

//ウィンドウを作成して開く
HWND hWnd = ::OpenWindow(tstrClassName, tstrTitleName, 800, 600, NULL);

//ウィンドウの表示
::ShowWindow(hWnd, SW_SHOW);

//メッセージ回転
while(::GetMessage(&msg, NULL, 0, 0) == TRUE)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

//終了
return msg.wParam;
}
    • good
    • 0
この回答へのお礼

出来ました。

マウスキャプチャーを使うとカーソル変更を自分で作らないといけないんですね。
てっきりマウスキャプチャーでも自動でカーソル変更出来ると思ってました。

これだったら自力で出来たと思うのですが、
「予期せぬ事態がおきるとWM_CANCELMODEが送られてくるので」ということなので、
聞いて良かったです。

カーソル変更はまだなのですが調べれば分かると思います。

何度も質問して申し訳ありませんでした。
ありがとうございます。

お礼日時:2009/06/18 19:37

 こんにちは。

度々すみません。
 補足にウィンドウ移動からリサイズ~とあったので、リサイズ枠をクリックすると、ウィンドウを移動してからリサイズする様にしてしまったのですが、当方の解釈ミスだったかもしれません。

 以下の3点を踏まえて改めて書き直します。

 (1)リサイズ枠でマウスの移動量が指定した移動量に達してからサイズ変更する
 (2)リサイズ枠を表示しないでサイズ変更を可能とする
 (3)リサイズ枠をクリックした瞬間にウィンドウが移動する訳ではない

#include<windows.h>
#include<commctrl.h>
#include<tchar.h>

#pragma comment(lib, "comctl32.lib")

const DWORD WS_EX_LAYERED = 0x80000;

//ウィンドウ領域を固定する為に記憶する変数
static RECT s_rcKeep = {0};

//ウィンドウクラス登録
static ATOM Regist(LPCTSTR szClassName, WNDPROC wndProc)
{
WNDCLASSEX wndclass = {sizeof(wndclass)};
wndclass.hCursor= ::LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon= NULL;
wndclass.lpszMenuName= NULL;
wndclass.lpszClassName= szClassName;
wndclass.hbrBackground= (HBRUSH)::GetStockObject(WHITE_BRUSH);
wndclass.hInstance= ::GetModuleHandle(NULL);
wndclass.style= 0;
wndclass.lpfnWndProc= wndProc;
wndclass.cbClsExtra= 0;
wndclass.cbWndExtra= 0;
return ::RegisterClassEx(&wndclass);
}
//ウィンドウを作成して開く
static HWND OpenWindow(LPCTSTR szClassName, LPCTSTR szTitleName, INT w, INT h, LPVOID pData)
{
HINSTANCE hInst = ::GetModuleHandle(NULL);

HWND hWnd = ::CreateWindowEx(WS_EX_TOOLWINDOW | /*WS_EX_LAYERED |*/ WS_EX_ACCEPTFILES, szClassName, szTitleName,
WS_POPUPWINDOW | WS_CLIPCHILDREN,// | WS_THICKFRAME,
CW_USEDEFAULT,CW_USEDEFAULT, w, h,
NULL, NULL,
hInst, pData);
return hWnd;
}

static LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}

static LRESULT OnClose(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
::DestroyWindow(hWnd);
return 0;
}

static LRESULT OnNCDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
::PostQuitMessage(0);
return 0;
}
//リサイズ枠がクリックされた
static LRESULT OnEnterSizeMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//ウィンドウ領域を取る
::GetWindowRect(hWnd, &s_rcKeep);
return 0;
}
//リサイズ枠が離された
static LRESULT OnExitSizeMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//リサイズ枠があったらスタイルを外す
const DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
if(dwStyle & WS_THICKFRAME)
{
::SetWindowLong(hWnd, GWL_STYLE, dwStyle & ~WS_THICKFRAME);
::SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
return 0;
}
//リサイズ中
static LRESULT OnSizing(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPRECT prc = (LPRECT)lParam;

//移動量
LONG lPct = 16;

//横に対して
if(((prc->right - s_rcKeep.right) % lPct))
{
//移動量に達さないのでs_rcKeepの値で固定
prc->right = s_rcKeep.right;
}
else
{
//移動量に達したのでs_rcKeepの値を更新
s_rcKeep.right = prc->right;
}

//縦に対して以下同様
if(((prc->bottom - s_rcKeep.bottom) % lPct))
{
prc->bottom = s_rcKeep.bottom;
}
else
{
s_rcKeep.bottom = prc->bottom;
}

return 0;
}
//ヒットテスト
static LRESULT OnHitTest(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//リサイズ枠と見なす幅
const INT ResizeEdge = 4;
POINT pt = {(short)LOWORD(lParam), (short)HIWORD(lParam)};

RECT rc;
::GetWindowRect(hWnd, &rc);

//移動領域がクリックされた事にする
if(pt.x <= rc.left + ResizeEdge || pt.y <= rc.top + ResizeEdge)
return HTCAPTION;

//クライアント領域がクリックされた事にする
if(pt.x <= rc.right - ResizeEdge && pt.y <= rc.bottom - ResizeEdge)
return HTCLIENT;

//此処まで来たらリサイズ枠の範囲内にいる事にする
//リサイズ枠のスタイルを入れる
const DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
::SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_THICKFRAME);

//右下へリサイズ領域がクリックされた事にする
if(pt.x >= rc.right - ResizeEdge && pt.y >= rc.bottom - ResizeEdge)
return HTBOTTOMRIGHT;

//右へリサイズ領域がクリックされた事にする
if(pt.x >= rc.right - ResizeEdge)
return HTRIGHT;

//下へリサイズ領域がクリックされた事にする
if(pt.y >= rc.bottom - ResizeEdge)
return HTBOTTOM;

return HTNOWHERE;
}

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:::OnCreate(hWnd, uMsg, wParam, lParam); break;
case WM_CLOSE:::OnClose(hWnd, uMsg, wParam, lParam); break;
case WM_NCDESTROY:::OnNCDestroy(hWnd, uMsg, wParam, lParam); break;
case WM_ENTERSIZEMOVE:::OnEnterSizeMove(hWnd, uMsg, wParam, lParam); break;
case WM_EXITSIZEMOVE:::OnExitSizeMove(hWnd, uMsg, wParam, lParam); break;
case WM_SIZING:::OnSizing(hWnd, uMsg, wParam, lParam); break;
case WM_NCHITTEST:return ::OnHitTest(hWnd, uMsg, wParam, lParam);
}

return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPSTR lpCmdLine, int nShowCmd)
{
const TCHAR tstrClassName[] = TEXT("test resize frame");
const TCHAR tstrTitleName[] = TEXT("title");
MSG msg;

::InitCommonControls();

//ウィンドウクラスの登録
::Regist(tstrClassName, &::WndProc);

//ウィンドウを作成して開く
HWND hWnd = ::OpenWindow(tstrClassName, tstrTitleName, 800, 600, NULL);

//ウィンドウの表示
::ShowWindow(hWnd, SW_SHOW);

//メッセージ回転
while(::GetMessage(&msg, NULL, 0, 0) == TRUE)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

//終了
return msg.wParam;
}

この回答への補足

度々すみません。

マウスキャプチャーでやってみているのですが、
ソースを書いて頂いたものとどう違うのでしょうか?

SetCapture()とReleaseCapture()を使用するみたいなのですが、
スタイルの変更を繰り返す方法と違うのでしょうか?

マウスキャプチャーでまだ出来ていないので分からないのですが、
リサイズ中にでる枠は表示されないのでしょうか?
もし、表示されないのであれば、
出来るだけマウスキャプチャーでやりたいので、
教えて頂ければ助かります。

最初質問する際に、リサイズ枠を表示しないでリサイズする方法と
書いておけば良かったのですが、
私の質問ミスでお手間を取らせてしまいすみません。

補足日時:2009/06/18 16:41
    • good
    • 0
この回答へのお礼

リサイズ枠の非表示(スタイルの変更を繰り返す)は確認できました。
何度も答えて頂きありがとうございます。

一応マウスキャプチャーでもやってみようと思います。
また何か分からないことがあれば質問させて頂きたいと思います。

マウスキャプチャーの事で分からない所がある可能性もあるので、
念のためにマウスキャプチャーで確認後に質問を締め切らせて頂きます。
質問内容が違うのですが。

ちなみに、最初の補足で質問させて頂いた内容については、
OnEnterSizeMove()関数でミスをしてしまっていたので出来なかっただけでした。
ご迷惑をおかけしました。
すみませんでした。

お礼日時:2009/06/18 13:26

 こんばんは。

すんません。
 OnHitTest()関数の処理に間違いがあったので修正しました。ウィンドウ領域を取るAPIはGetClientRect()ではなくGetWindowRect()です。(複雑化して来ているので中々ぴっしりと成功させるのは困難です・・・)。

static LRESULT OnHitTest(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//リサイズフレームを入れる
const DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
::SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_THICKFRAME);

POINT pt = {(short)LOWORD(lParam), (short)HIWORD(lParam)};

RECT rc;
::GetWindowRect(hWnd, &rc);

//キャプション領域がクリックされた事にする
//不用ならコメントアウトして下さい
if(pt.x <= rc.left + 4 || pt.y <= rc.top + 4)
return HTCAPTION;

//右へリサイズ領域がクリックされた事にする
if(pt.x >= rc.right - 4)
return HTRIGHT;

//下へリサイズ領域がクリックされた事にする
if(pt.y >= rc.bottom - 4)
return HTBOTTOM;

//其れ以外はクライアント領域がクリックされた事にする
return HTCLIENT;
}
    • good
    • 0

 こんばんは。

補足頂きました。

 遅れてしまってすんません。悪戦苦闘しておりました。移動の方は解決されたようですので、
・サイズ変更枠の見た目が悪いので、表示しないようにする、又は分かりにくいようにすること
 に関してですが、WS_THICKFRAMEのスタイルを無くした場合、リサイズ関連のメッセージが受け取れなくなる為、マウスのキャプチャーと言う芸当を使用するか、WM_NCHITTESTで巧みにスタイルの変更を繰り返せば、非表示のリサイズ枠処理が出来ます。
 以下はクリックする度に、x,y座標が+10づつ加算されて移動する事と同時に、リサイズ枠無しで、リサイズ処理をしています。以下参考程度に。

#include<windows.h>
#include<commctrl.h>
#include<tchar.h>

#pragma comment(lib, "comctl32.lib")

const DWORD WS_EX_LAYERED = 0x80000;

//移動量
static POINT s_ptMoved = {10, 10};

//確保
static RECT s_rcKeep = {0};

//ウィンドウクラス登録
static ATOM Regist(LPCTSTR szClassName, WNDPROC wndProc)
{
WNDCLASSEX wndclass = {sizeof(wndclass)};
wndclass.hCursor= ::LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon= NULL;
wndclass.lpszMenuName= NULL;
wndclass.lpszClassName= szClassName;
wndclass.hbrBackground= (HBRUSH)::GetStockObject(WHITE_BRUSH);
wndclass.hInstance= ::GetModuleHandle(NULL);
wndclass.style= 0;
wndclass.lpfnWndProc= wndProc;
wndclass.cbClsExtra= 0;
wndclass.cbWndExtra= 0;
return ::RegisterClassEx(&wndclass);
}

//ウィンドウを作成して開く
static HWND OpenWindow(LPCTSTR szClassName, LPCTSTR szTitleName, INT w, INT h, LPVOID pData)
{
HINSTANCE hInst = ::GetModuleHandle(NULL);

HWND hWnd = ::CreateWindowEx(WS_EX_TOOLWINDOW | /*WS_EX_LAYERED |*/ WS_EX_ACCEPTFILES, szClassName, szTitleName,
WS_POPUPWINDOW | WS_CLIPCHILDREN,// | WS_THICKFRAME,
CW_USEDEFAULT,CW_USEDEFAULT, w, h,
NULL, NULL,
hInst, pData);
return hWnd;
}

static LRESULT OnCreate(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return 0;
}

static LRESULT OnClose(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
::DestroyWindow(hWnd);
return 0;
}

static LRESULT OnNCDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
::PostQuitMessage(0);
return 0;
}

static LRESULT OnEnterSizeMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//ウィンドウ領域を取る
::GetWindowRect(hWnd, &s_rcKeep);

//移動量を加算する
s_rcKeep.left+= s_ptMoved.x;
s_rcKeep.top+= s_ptMoved.y;

//リサイズ無しで加算する
::SetWindowPos(hWnd, NULL, s_rcKeep.left, s_rcKeep.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

//移動後のウィンドウ領域を取る
::GetWindowRect(hWnd, &s_rcKeep);

return 0;
}

//マウスボタンが離された時に送られる
static LRESULT OnExitSizeMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//リサイズ枠を無くす
const DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
::SetWindowLong(hWnd, GWL_STYLE, dwStyle & ~WS_THICKFRAME);
::SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
return 0;
}

static LRESULT OnSizing(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPRECT prc = (LPRECT)lParam;

//移動量
LONG lPct = 16;

//x, yのドラッグ位置を合わせる
prc->left= s_rcKeep.left;
prc->top= s_rcKeep.top;

//横に対して
if(((prc->right - s_rcKeep.right) % lPct))
{
//移動量に達さないのでs_rcKeepの値で固定
prc->right = s_rcKeep.right;
}
else
{
//移動量に達したのでs_rcKeepの値を更新
s_rcKeep.right = prc->right;
}

//縦に対して以下同様
if(((prc->bottom - s_rcKeep.bottom) % lPct))
{
prc->bottom = s_rcKeep.bottom;
}
else
{
s_rcKeep.bottom = prc->bottom;
}

return 0;
}

static LRESULT OnHitTest(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//リサイズ枠を入れるが、表示はされない
const DWORD dwStyle = ::GetWindowLong(hWnd, GWL_STYLE);
::SetWindowLong(hWnd, GWL_STYLE, dwStyle | WS_THICKFRAME);

POINT pt = {(short)LOWORD(lParam), (short)HIWORD(lParam)};

RECT rc;
::GetClientRect(hWnd, &rc);

if(pt.x > rc.right - 4)
return HTRIGHT;

if(pt.y > rc.bottom - 4)
return HTBOTTOM;

return HTCLIENT;
}

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE: ::OnCreate(hWnd, uMsg, wParam, lParam); break;
case WM_CLOSE: ::OnClose(hWnd, uMsg, wParam, lParam); break;
case WM_NCDESTROY: ::OnNCDestroy(hWnd, uMsg, wParam, lParam); break;
case WM_ENTERSIZEMOVE: ::OnEnterSizeMove(hWnd, uMsg, wParam, lParam); break;
case WM_EXITSIZEMOVE:::OnExitSizeMove(hWnd, uMsg, wParam, lParam); break;
case WM_SIZING:::OnSizing(hWnd, uMsg, wParam, lParam); break;
case WM_NCHITTEST:return ::OnHitTest(hWnd, uMsg, wParam, lParam);
}

return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hInstancePrev, LPSTR lpCmdLine, int nShowCmd)
{
const TCHAR tstrClassName[] = TEXT("test resize frame");
const TCHAR tstrTitleName[] = TEXT("title");
MSG msg;

::InitCommonControls();

//ウィンドウクラスの登録
::Regist(tstrClassName, &::WndProc);

//ウィンドウを作成して開く
HWND hWnd = ::OpenWindow(tstrClassName, tstrTitleName, 800, 600, NULL);

//ウィンドウの表示
::ShowWindow(hWnd, SW_SHOW);

//メッセージ回転
while(::GetMessage(&msg, NULL, 0, 0) == TRUE)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

//終了
return msg.wParam;
}
    • good
    • 0

 こんばんは。


 其の侭WS_THICKFRAMEを付加してから、WM_ENTERSIZEMOVEで初回ドラッグとしてウィンドウ矩形領域を記憶、WM_SIZINGで移動量の制限をかけて見ては如何でしょう。以下参考程度に。

//固定ウィンドウ領域を記憶する為の変数
static RECT s_rcKeep = {0};

//ウィンドウ枠が初めてドラッグされた時に1回だけ呼ばれる
static LRESULT OnEnterSizeMove(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//ウィンドウ枠を含めた矩形領域を記憶
::GetWindowRect(hWnd, &s_rcKeep);
return 0;
}

//ウィンドウ枠をドラッグしている間、リアルタイムで送られてくる
static LRESULT OnSizing(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//lParamにはドラッグされているスクリーン領域が入っている
LPRECT prc = (LPRECT)lParam;

//移動量(16ピクセル動くごとに16ピクセル分幅が広がる)
LONG lPct = 16;

//横に対して
if(((prc->right - s_rcKeep.right) % lPct))
{
//移動量に達さないのでs_rcKeepの値で固定
prc->right = s_rcKeep.right;
}
else
{
//移動量に達したのでs_rcKeepの値を更新
s_rcKeep.right = prc->right;
}

//縦に対して以下同様
if(((prc->bottom - s_rcKeep.bottom) % lPct))
{
prc->bottom = s_rcKeep.bottom;
}
else
{
s_rcKeep.bottom = prc->bottom;
}

return 0;
}

LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_ENTERSIZEMOVE : ::OnEnterSizeMove(hWnd, uMsg, wParam, lParam); break;
case WM_SIZING: ::OnSizing(hWnd, uMsg, wParam, lParam); break;
}

return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

この回答への補足

一応出来たのですが、
ウィンドウを移動してサイズ変更しようとすると、
右下の座標が移動する前の座標のままなので、
クリックしてもサイズ変更しなかった場合に、
右下がそこの座標のままになってしまうのですが、
どうすればいいのでしょうか?


それと、これはこういうことが出来たら良いなという事なので
答えて頂かなくても良いです。
サイズ変更枠の見た目が悪いので、
表示しないようにする、又は分かりにくいようにすることは出来るのでしょうか?

補足日時:2009/06/17 19:16
    • good
    • 0
この回答へのお礼

出来ました。

私のミスで出来なかっただけでした。
すみません。

もし良ければでいいので、サイズ変更枠を表示しないようにする、
又は、分かりにくいようにすることは出来るのでしょうか?
もちろん、今のままサイズ変更が出来る状態のままです。

何度も質問して申し訳ありません。

お礼日時:2009/06/17 22:44

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報