タイトルバーの制御
タイトルバーの制御
WINDOWのタイトルバーの自作がしたいです。
例をとってみるとCHROMEのように丸みを帯びていたり、IEのように複数ボタンを置いたり画像を張ったりなどです。
調べても「WM_NCHITTESTと自分でゴリゴリ描画」などという曖昧なことしかわかりませんでした。
タイトルバーに描画をする方法・タイトルバーに子ウィンドウのようにオブジェクトを置く方法・イベントを設置・検出する方法・タイトルバーの場所や大きさの変更方法が知りたいです。
また、DXLIBは使わない方法でお願いします。
OS: WINDOWS7
コンパイラ: GCC (MINGW-W64)
です
Re: タイトルバーの制御
あまり詳しくないのですが、回答がないようなので概要だけ。
タイトルバーなどの非クライアントエリアを描画するためには、幾つか方法があるようです。
GetWindowDC() 関数で取得したデバイスコンテキストは、ウィンドウ全体に描画出来ます。
WM_NCPAINT をハンドルして、描画する方法もあります。Windows 標準でないデザインにするので、「自分でゴリゴリ描画」するしかないですね。
Chrome は全体の枠(フレーム)がひとつのウィンドウで、各タブも一つ一つがウィンドウです。
Chrome が使用しているかどうかは分かりませんが、矩形以外のウインドウはリージョンを設定すれば出来ます。
IE でもそうなのですが、Chrome ではページ内に表示されているボタンやエディットボックスのように見えるものは Windows 標準のコントロールではありません。すべてプログラムで描画しているようです。
タイトルバーなどの非クライアントエリアを描画するためには、幾つか方法があるようです。
GetWindowDC() 関数で取得したデバイスコンテキストは、ウィンドウ全体に描画出来ます。
WM_NCPAINT をハンドルして、描画する方法もあります。Windows 標準でないデザインにするので、「自分でゴリゴリ描画」するしかないですね。
Chrome は全体の枠(フレーム)がひとつのウィンドウで、各タブも一つ一つがウィンドウです。
Chrome が使用しているかどうかは分かりませんが、矩形以外のウインドウはリージョンを設定すれば出来ます。
IE でもそうなのですが、Chrome ではページ内に表示されているボタンやエディットボックスのように見えるものは Windows 標準のコントロールではありません。すべてプログラムで描画しているようです。
Re: タイトルバーの制御
返信遅れてすいません。
chromeは各タブがウィンドウだったのですね。知りませんでした。
矩形以外のウィンドウはリージョンを使えばできたのですか。
ボタンやエディットボックスなどは子ウィンドウみたいなのを使って描画してるんですかね?あれも全部プログラムで描画していたのですか
ありがとうございました
chromeは各タブがウィンドウだったのですね。知りませんでした。
矩形以外のウィンドウはリージョンを使えばできたのですか。
ボタンやエディットボックスなどは子ウィンドウみたいなのを使って描画してるんですかね?あれも全部プログラムで描画していたのですか
ありがとうございました
Re: タイトルバーの制御
あらかじめお断りします。以前に書いたことやこれから書くとは私が独自で調査したものあるいは、想像で書いているもので、必ずしも正しいとは限りません。
その点、ご承知置きください。
まず訂正からになってしまってすいません。
タブの部部をドラッグするとタブを分離できるので、子ウインドウの一部かと思っていましたが、そうではなく移動を始めた瞬間に別に外枠となるウインドウを用意しているのだと思います。あくまでも想像ですが。
繰り返しになりますが、Chrome はウィドウに関しては非常にシンプルな作りです。外枠である親ウインドウと、現在開いているページを表示するための複数の子ウインドウから成り立ちます。つまり、現在開いているページ+1のウインドウしか使っていません。
もちろん、プログラムをべた書きしているわけではなく、Google 独自のクラスライブラリあるいはフレームワークのようものを作って、使っているんだと思いますが、詳細はわかりません。
各ページのリンクとか動画の再生とかボリュームのスライダーとかすべて独自に一つのウィンドウの中で描画/処理しているようですね。デザインの自由度は高くなりますが、プログラミングの難易度は相当高そうです。
IE に関しては、ウィンドウをふんだんに使用しています。しかしやっぱり Windows 標準のボタンコントロールやエディットコントロールは使用していません。家のマーク(ホーム)や星のマーク(お気に入り)や歯車のマーク(ツール)もたぶんビットマップだと思います。(リソースに見つからなかったので違うかもしれませんが)
これらは一つのウインドウ内に書かれていますが、イベントに関しては正直よく分りません。
その点、ご承知置きください。
まず訂正からになってしまってすいません。
これは違いました。タブの部分を含めて子ウインドウだと思っていたのですが、親ウインドウ(フレーム)に書かれていました。タブのクリックで表示するページが切り替わりますが、これらは Windows のタブコントロールといったものは使ってないようです。自前でやっているのでしょうが、具体的な方法はわかりません。
タブの部部をドラッグするとタブを分離できるので、子ウインドウの一部かと思っていましたが、そうではなく移動を始めた瞬間に別に外枠となるウインドウを用意しているのだと思います。あくまでも想像ですが。
繰り返しになりますが、Chrome はウィドウに関しては非常にシンプルな作りです。外枠である親ウインドウと、現在開いているページを表示するための複数の子ウインドウから成り立ちます。つまり、現在開いているページ+1のウインドウしか使っていません。
いえ、ウインドウではありません。ボタンはたぶんビットマップか直接描画しているのでしょう。エディットボックスは枠だけ書いているのでしょうね。文字の入力とかは全部自前でプログラムでやっていると思われます。
もちろん、プログラムをべた書きしているわけではなく、Google 独自のクラスライブラリあるいはフレームワークのようものを作って、使っているんだと思いますが、詳細はわかりません。
各ページのリンクとか動画の再生とかボリュームのスライダーとかすべて独自に一つのウィンドウの中で描画/処理しているようですね。デザインの自由度は高くなりますが、プログラミングの難易度は相当高そうです。
IE に関しては、ウィンドウをふんだんに使用しています。しかしやっぱり Windows 標準のボタンコントロールやエディットコントロールは使用していません。家のマーク(ホーム)や星のマーク(お気に入り)や歯車のマーク(ツール)もたぶんビットマップだと思います。(リソースに見つからなかったので違うかもしれませんが)
これらは一つのウインドウ内に書かれていますが、イベントに関しては正直よく分りません。
Re: タイトルバーの制御
タイトルバーをなくして、全部クライアント領域にすれば、
なんでも置けるのではありませんか?
試しにこんなのを書いてみました。
#include <windows.h>
HWND hButton;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_COMMAND:
if ((HWND)lp == hButton) DestroyWindow(hwnd);
return 0;
case WM_LBUTTONDOWN:
ReleaseCapture();
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
return 0;
case WM_NCHITTEST:
{
LRESULT res = DefWindowProc(hwnd, WM_NCHITTEST, wp, lp);
return (res == HTCLIENT) ? HTCAPTION : res;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rect { 20, 40, 400, 65 };
DrawText(hdc, "タイトルバーはありません", -1, &rect, DT_CENTER);
EndPaint(hwnd, &ps);
return 0;
}
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, PSTR ln, int sh)
{
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = inst;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)WHITE_BRUSH;
winc.lpszMenuName = NULL;
winc.lpszClassName = "Class";
if (!RegisterClass(&winc)) return -1;
HWND hwnd = CreateWindow(
"Class", NULL, WS_BORDER | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, inst, NULL
);
if (hwnd == NULL) return -1;
LONG style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~WS_CAPTION;
style |= WS_BORDER;
style = SetWindowLong(hwnd, GWL_STYLE, style);
hButton = CreateWindow("BUTTON", "X",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
600, 20, 25, 25, hwnd, NULL, inst, NULL);
if (hButton == NULL) return -1;
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Re: タイトルバーの制御
>> Bullさん
私の環境でコンパイルしてみたのですが、タイトルバーは消えることなくしっかり残ってしまっていました,,,
Win7 64bit, MinGW GCCでコンパイル、実行しております
少し話ずれますが、27行目RECT rect直後のイコール抜けてますよ
Re: タイトルバーの制御
Bullさんはコードを示していません。
あなたが書いたタイトルバーが消えるそのプログラムを貼り付けてください。
#5 のプログラムですね。
これは、C++11 以降の C++プログラムなので、= なしで初期化できます。
gcc の代わりに g++ でコンパイルするか、ソースファイルの拡張子を
.c ではなく .cpp にして gcc でコンパイルしてみてください。
MingW GCC に C++コンパイラが含まれないのであれば、= を付けてください。
このプログラムは、~WS_CAPTION でタイトルバーが出ないようになっています。
全部がクライアント領域であることを示すために、そこを灰色にしたコードに
変更します。これでどうですか?
#include <windows.h>
HWND hButton;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_COMMAND:
if ((HWND)lp == hButton) DestroyWindow(hwnd);
return 0;
case WM_LBUTTONDOWN:
ReleaseCapture();
SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
return 0;
case WM_NCHITTEST:
{
LRESULT res = DefWindowProc(hwnd, WM_NCHITTEST, wp, lp);
return (res == HTCLIENT) ? HTCAPTION : res;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rect = { 100, 200, 400, 300 };
DrawText(hdc, "ここは、クライアント領域です", -1, &rect, DT_CENTER);
EndPaint(hwnd, &ps);
return 0;
}
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, PSTR ln, int sh)
{
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = inst;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)LTGRAY_BRUSH;
winc.lpszMenuName = NULL;
winc.lpszClassName = "Class";
if (!RegisterClass(&winc)) return -1;
HWND hwnd = CreateWindow(
"Class", "TITLE", WS_BORDER | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, inst, NULL
);
if (hwnd == NULL) return -1;
LONG style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~WS_CAPTION;
style |= WS_BORDER;
style = SetWindowLong(hwnd, GWL_STYLE, style);
hButton = CreateWindow("BUTTON", "終了",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
100, 400, 60, 30, hwnd, NULL, inst, NULL);
if (hButton == NULL) return -1;
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Re: タイトルバーの制御
>>かずまさん
申し訳ございません。
かずまさんのプログラムでした。
C++11以降ですと = なしで初期化可能という使用があったのですね、知りませんでした。
このように表示されていたため、青い部分がタイトルバーだと勘違いしていました。
ありがとうございました。
申し訳ございません。
かずまさんのプログラムでした。
C++11以降ですと = なしで初期化可能という使用があったのですね、知りませんでした。
このように表示されていたため、青い部分がタイトルバーだと勘違いしていました。
ありがとうございました。