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
宜しくお願い致します。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/10/19 06:50