質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

6762閲覧

子ウィンドウを閉じる方法

BeatStar

総合スコア4958

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/10/19 02:46

C/C++ ( Windows API 実装あり ) でやっています。

DLLに ウィンドウ( ダイアログに相当? )を格納しておいて、
実行ファイルから動的リンクで(DLLの方の)ウィンドウを表示し、データを取得したいと思います。
格納するウィンドウはいくつかあり、

オリジナル? の バージョンダイアログ ( ウィンドウ ),
ウィンドウやコントロールの色と文字の色を取得するウィンドウ
etc.

です。

バージョンダイアログはなんとか成功したのですが、
コントロールの色&文字色 を取得する ウィンドウが...

ウィンドウを生成する場合は hInstance が必要なので、実行ファイル(呼び出し元) の hInstance を引数として渡します。

C++

1#include<Windows.h> 2#include<string> 3 4 5using namespace std; 6 7 8// コントールID 9const int ID_FORECOLOR = 102; 10const int ID_BGCOLOR = 103; 11const int ID_OKBUTTON = 104; 12 13 14/* 15 クラスのメンバにするのいいが、 16WindowsAPIの ウィンドウプロシージャはstaticでないといけないらしいので、あまり意味がない... 17*/ 18COLORREF g_foreColor, g_bgColor; 19 20 21// チェックのため。 22void MsgBox( const std::string str ){ 23 MessageBox( NULL, str.c_str(), NULL, MB_OK ); 24} 25 26 27// 「Win32 API入門」(http://wisdom.sakura.ne.jp/system/winapi/) 28// ->「コモンコントロール」 29// ->「色の選択」 30// 機能: ChooseColorダイアログを表示し、色を取得する 31bool ShowChooseColor( HWND hWnd, COLORREF defaultColor, COLORREF *result ){ 32 BOOL bStatus; 33 34 CHOOSECOLOR cc = { 0 }; 35 36 COLORREF CustColors[16]; 37 38 cc.lStructSize = sizeof( CHOOSECOLOR ); 39 cc.hwndOwner = hWnd; 40 cc.rgbResult = defaultColor; 41 cc.lpCustColors = CustColors; 42 cc.Flags = CC_PREVENTFULLOPEN | CC_RGBINIT; 43 44 bStatus = ChooseColor( &cc ); 45 46 *result = cc.rgbResult; 47 48 if( bStatus == TRUE ){ 49 return true; 50 }else{ 51 return false; 52 } 53} 54 55 56 57LRESULT CALLBACK WndProc2( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ){ 58 static HWND hStatic1, hStatic2; 59 static HWND hBgColor, hForeColor, hOK; 60 61 switch( msg ){ 62 case WM_CREATE: 63 hStatic1 = CreateWindow( 64 "STATIC", 65 EXT("ウィンドウの色:"), 66 WS_CHILD | WS_VISIBLE|SS_RIGHT, 67 60, 20, 68 110, 20, 69 hWnd, 70 NULL, 71 ((LPCREATESTRUCT)(lp))->hInstance, 72 NULL 73 ); 74 75 hStatic2 = CreateWindow( 76 "STATIC", 77 TEXT("文字の色:"), 78 WS_CHILD | WS_VISIBLE|SS_RIGHT, 79 60, 20+21, 80 110, 20, 81 hWnd, 82 NULL, 83 ((LPCREATESTRUCT)(lp))->hInstance, 84 NULL 85 ); 86 87 // 背景色選択 88 hBgColor = CreateWindow( 89 TEXT("BUTTON"), 90 TEXT("選択"), 91 WS_CHILD | WS_VISIBLE, 92 171+100, 20, 93 400, 20, 94 hWnd, 95 (HMENU)ID_BGCOLOR, 96 ((LPCREATESTRUCT)(lp))->hInstance, 97 NULL 98 ); 99 100 // 文字の色選択 101 hForeColor = CreateWindow( 102 TEXT("BUTTON"), 103 TEXT("選択"), 104 WS_CHILD | WS_VISIBLE, 105 171, 20+21, 106 400, 20, 107 hWnd, 108 (HMENU)ID_FORECOLOR, 109 ((LPCREATESTRUCT)(lp))->hInstance, 110 NULL 111 ); 112 113 // "OK"ボタン。 これを押されたら結果を返して戻る。 114 hOK = CreateWindow( 115 TEXT("BUTTON"), 116 TEXT("OK"), 117 WS_CHILD | WS_VISIBLE, 118 171, 20+21+21+21, 119 400, 20, 120 hWnd, 121 (HMENU)ID_OKBUTTON, 122 ((LPCREATESTRUCT)(lp))->hInstance, 123 NULL 124 ); 125 return 0; 126 case WM_COMMAND: 127 switch( LOWORD(wp) ){ 128 case ID_BGCOLOR: 129 // グローバル変数の方に格納する 130 ShowChooseColor( hWnd, 0, &g_foreColor ); 131 break; 132 case ID_FORECOLOR: 133 // グローバル変数の方に格納する 134 ShowChooseColor( hWnd, 0, &g_bgColor ); 135 break; 136 case ID_OKBUTTON: 137 SendMessage( hWnd, WM_DESTROY, 0, 0 ); 138 break; 139 } 140 return 0; 141 case WM_DESTROY: 142 PostQuitMessage(0); 143 return 0; 144 } 145return DefWindowProc( hWnd, msg, wp, lp ); 146} 147 148 149extern "C" __declspec(dllexport) 150bool ShowColorWindow( int x, int y, HINSTANCE hInstance, HICON hIcon, COLORREF *foreColor, COLORREF *bgColor ){ 151 MSG msg; 152 WNDCLASSEX w; 153 154 w.cbSize = sizeof(WNDCLASSEX); 155 w.style = CS_HREDRAW | CS_VREDRAW; 156 w.lpfnWndProc = WndProc2; 157 w.cbWndExtra = w.cbClsExtra = 0; 158 w.hInstance = hInstance; 159 w.hIcon = hIcon; 160 w.hIconSm = w.hIcon; 161 w.hCursor = LoadCursor(NULL , IDC_ARROW); 162 w.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(240,240,240)); 163 w.lpszClassName = TEXT( "Prog" ); 164 w.lpszMenuName = NULL; 165 166 if( RegisterClassEx( &w ) == 0 ) return -1; 167 168 HWND hWnd = CreateWindow( TEXT( "Prog" ), TEXT("色の設定"), WS_BORDER|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, x, y, 600, 200-50+20, NULL, NULL, hInstance, NULL ); 169 170 if( hWnd == NULL ) return -2; 171 172 ShowWindow( hWnd, SW_SHOW ); 173 174 while( true ){ 175 GetMessage( &msg, NULL, 0, 0 ); 176 DispatchMessage( &msg ); 177 } 178 179 // グローバル変数 -> 引数 で戻り値扱いにする 180 *foreColor = g_foreColor; 181 *bgColor = g_bgColor; 182 183return 0; 184}

コントロールの X座標,Y座標,高さ,幅 はでたらめです。
( コンパイルが通るかどうかや、動くかどうかを先にチェックするため。 )

ウィンドウは表示されたのですが、
挙動が...

ID_FORECOLOR, ID_BGCOLOR のコントロールはうまくいったのですが、

ID_OKBUTTON を押しても このウィンドウが表示されたままで、
システム(?) の "閉じる" ボタン ( "×" ) を押して消しました。

で、実行ファイルの方を再度コンパイル&移動すると、

「アクセス不可」のようなエラーに。

なので、タスクマネージャで見てみると
プロセスの欄に 実行ファイルの名前が...

"プロセスの終了" をして、再度コンパイルするとできました。

私が思うに、

実行ファイルから hInstance を渡す
-> hWnd が hInstace から作成される
-> 元の hWnd が同じであるためSendMessageでWM_DESTROYメッセージを送っても 呼び出し元の実行ファイルの方になる
-> DLLの方のウィンドウが残っているため、"プロセス"には 実行ファイルの方として"生存している"とみなされる

です。

(理由が)わかってはいても、どうすればいいか...

変数名を変えても中身が同じなら、同じデータとして扱われるし、
hInstance に でたらめな数値を入れて渡しても、 もし他のソフトで同じ値を使っている場合なら...

どうすれば回避できるでしょうか。

[環境等]
言語: C/C++
コンパイラ: (DLLは) VC++, (実行ファイルは) MinGW

宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

プロセスが終了しなかった理由ですが、「文字通り」プログラムが終了していなかったからです。
ShowColorWindow関数をご覧ください。

C

1while( true ){ 2 GetMessage( &msg, NULL, 0, 0 ); 3 DispatchMessage( &msg ); 4} 5```どのようなときにこのループは終了しますか? 6というのが答えです。ウインドウが破棄されてもここから出られず、return文に到達しなかったため、プログラムが終了しなかったのです。 7なので、メッセージIDをチェックしてループを抜ける処理を追加すると正しく動作するようになります。 8```C 9int ret; 10while( true ){ 11 ret = GetMessage( &msg, NULL, 0, 0 ); 12 if( ret == -1 ) break; 13 DispatchMessage( &msg ); 14 if( ret == WM_DESTROY ) break; /* WM_QUITではない */ 15}

投稿2016/10/19 03:24

編集2016/10/19 06:35
majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BeatStar

2016/10/19 06:50

なるほど。 そいう風にすればいいんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問