C/C++ ( Windows API 実装 ) でやっています。
Excel VBA もいじったりしているのですが、
Excel VBA で フォームモジュールでUserForm ( 以下 UF ) 内の コントロール をモジュール内から操作することできますよね。
VBA
1' ボタン ( Button1 ) が押されたときの挙動 2TextBox1.Height = 300 ' テキストボックスの高さを 300 にする
みたいに。
VBAでできる
■ BorderColor : 枠の色の変更及び取得 ■ BorderStyle : 枠の有無? ■ SpecialEffect: フラットにするとか
がC/C++のGUIでもできたらいいのですが...
私はコントロールをクラス化しています。
[定義] + : public member(s) # : protected member(s) - : private member(s) // ~ : explanation
たとえば EDITコントロール 用クラスを WEdit クラスとすると
[WEdit] + WEdit(HWND,int) // コンストラクタ + ~WEdit() // デストラクタ + Create(x,y,w,h,caption) : HWND + SetText(const std::string) : bool + GetText(void) : std::string + Visible(bool) ... // その他のメンバ関数 - hWnd : HWND // 親ウィンドウハンドル - ControlID : int // コントロールID
みたいにしています。
コンストラクタで 親ウィンドウハンドルとコントロールIDを引き受けて メンバ変数にセット。
それ以降は メンバ変数にアクセス...
という感じで。
また、コントロール独特のもの ( EDIT なら マルチラインなのか そうじゃないのか等 ) もありますから、
それは 今のところコンストラクタに渡しています。
このクラス( 複数 ) に 「枠の取り消し・出現」と 「フラットにする・しない」のメンバ関数を追加したいのです。
できたら枠の色も変更できたらいいですが、コントロールの色づけが WM_CTLCOLOREDITメッセージのところだったりと限定的なのでちょっと面倒。
そこから考えて、枠の色ももしかすると大体そんな感じだろうと推測しますから 無くてもいいです。
ですが、 「枠の取り消し・出現」と 「フラットにする・しない」 は 必ず入れたいのです。
枠のやつは Border ですから ウィンドウスタイルとして
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT
渡していますから これ( WS_BORDER ) を外せばいいとわかります。
ウィンドウスタイルはGetWindowLong関数で取得できたはず ( 入門系のサイトには書かれている場合が多い? ) ので
実際に試してみました。
WEditクラスから オブジェクト Edit1 を生成して, Createメンバ関数で生成, その後 クラス外 ( 呼び出し側 ) で GetWindowLongを使って「WS_BORDER」があるかどうか
をチェックしてみました。
ウィンドウスタイルは ビット演算らしいので &演算子 ? で抽出してみました。
( Createメンバ関数 内で スタイルの設定は WS_BORDER が入っているとします。 )
C++
1// WM_CREATEメッセージ内: 2 3WEdit* Edit1 = new WEdit( hWnd, 102 ); 4 5HWND hEdit = Edit1->Create( 0, 0, 100, 20, "" ); 6 7DWORD dwStyle; // スタイルは DWORDだったはずなので。 8 9dwStyle = (DWORD)GetWindowLong( hEdit, GWL_STYLE ); 10 11if( dwStyle & WS_BORDER ){ 12 MessageBox( hWnd, "Found", "Result", MB_OK ); 13}else{ 14 MessageBox( hWnd, "Not Found", "Result", MB_OK ); 15} 16 17// ※ オブジェクトの破棄は デストラクタ内で。
のようにしてみました。
( 実際には MessageBox等もクラス化していたりしていますが、説明のため。 )
それでCompile and Run したところ、
"Not Found" というメッセージボックスが表示されました。
Createメンバ関数での スタイル の部分ではちゃんと WS_BORDERがセットされているのに...
別の コントロール独自のスタイル ( ES_MULTILINE 等? ただし、設定されているやつ。 ) をチェックしてみたところ、
"Found" でした。
ヘルプファイルで"GetWindowLong" を検索すると関連ページとして "GetWindowLongPtr" がありました。
そのページを見ると「この関数は、GetWindowLong 関数の改訂版です」とあるので、
関数を GetWindowLong から GetWindowLongPtr に切り替えてみましたが結果は同じでした。
WS_*** のやつは 無理なのでしょうか?
それともやり方が別にあるのでしょうか?
ソースコードを(私が)提示するのは構いませんが、
私用のライブラリとして固めていて、ごちゃごちゃしているので...
[情報]
言語 : C/C++
WindowsAPI : あり
環境 : MinGW ( g++ )
聞きたいこと: コントロールの操作関連 ( 特に Border系と フラットにすること )
宜しくお願い致します。
Chironianさん ご回答ありがとうございます。
ご回答ありがとうございます。
外出先で質問&アンサーしているので、
帰宅後に試してみました。
まず "3. WM_BORDERが設定されていても..." の方が怪しいと仰ったので、
先に試してみました。
ShowWindow( hEdit, SW_SHOW ); // Edit1 を Show!
を置いて やっても同じでした。
次に "1. そもそもウィンドウハンドルではない" をチェックしてみました。
C++
1LRESULT CALLBACK EditProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ){ 2 // 省略。 EDITのサブクラスってとこ。 3} 4 5 6 7LRESULT CALLBACK WindProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp ){ 8 static CMsgBox MsgBox(hWnd); // MessageBoxをクラス化したもの。 9 static WEdit* Edit1; // 質問にあるWEditクラスのオブジェクト 10 static HWND hEdit; // Edit1 のウィンドウハンドル 11 CWindowInfo* Info; // ウィンドウの情報を取得する自作クラス 12 DWORD dwStyle; 13 14 switch( msg ){ 15 case WM_CREATE: 16 Edit1 = new WEdit( hWnd, 102, EditProc ); // 引数そのものは正しいとする。定義を書くのが面倒なので。 17 hEdit = Edit1->Create( 0, 0, 20, 100 ); // これも正しいとする。 18 ShowWindow( hEdit, SW_SHOW ); 19 break; 20 case WM_RBUTTONDOWN: 21 // 右クリックされたら Edit1 の情報 ( 特に ウィンドウスタイル ) を取得する 22 Info = new CWindowInfo( hWnd, 102 ); 23 24 dwStyle = Info->GetStyle(); 25 26 if( dwStyle & WS_BORDER ){ 27 MsgBox.Show( "Found" ); // WS_BORDER があれば "Found" というメッセージボックスを表示 28 }else{ 29 MsgBox.Show( "Not Found" ); 30 } 31 32 // 試しに Edit1 を非表示にしてみる。 33 ShowWindow( hEdit, SW_HIDE ); 34 delete Info; 35 break; 36 case WM_DESTROY: 37 delete Edit1; 38 PostQuitMessage( 0 ); 39 break; 40 } 41return DefWindowProc( hWnd, msg, wp, lp ); 42}
みたいにしました。
すると、
"Not Found" というMessageBox表示後、 Edit1 に相当する部分が非表示になりました。
非表示になるということは、hEdit は ウィンドウハンドルで、ちゃんと格納されているってことですよね。
なので
1 & 3 は違うと思います。
"2. そもそも WS_BORDERが設定されていない" ... (パターンからすると)ありえそうですが、
コードを見ると設定されていると思います。
( 実際、実行時も 黒のボーダーが Edit1 に相当する部分に出ていますから。 )
よって、2もあり得ないと思います。
Chironianさん。
どうしてもパターンが思いつかない
( 一応、思いついたものはすべてやりました。 )
のでネットで検索したところ、
エディットコントロール [VC++の使い方] - トップ [nitoyon . com]
がヒットしました。
これによると
リソースエディタで作成するような枠をつけたい場合は、 WS_EX_CLIENTEDGE スタイルを有効にするのがよいでしょう。 CreateWindowEx(WS_EX_CLIENTEDGE, ...); とします。 (省略した残りの引数は、CreateWindow 関数と同じものを書く。 ただし、WS_BORDER ははずしておいたほうがよいでしょう)
とありました。
なので
1. ( Createメンバ関数内 ) CreateWindowEx の第一引数としてWS_EX_CLIENTEDGE を渡し、 通常のウィンドウスタイルから WS_BORDER をはずしておく 2. ( SetBorderメンバ関数が呼ばれたら ) WS_EX_CLIENTEDGE を外す
みたいにしようかと思っています。
ありがとうございます!!
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/05/22 04:26
2017/05/22 04:48 編集
2017/05/27 05:57
2017/05/27 06:01
2017/05/27 07:13