なんかやっぱり流行りというかAndroid関連での検索が引っかかってくる今日この頃。
そんな中 windowsformアプリ関連(C++/CLI)のことをちょこっと。しかも今更な内容。
正直Windowsアプリはwin32APIでゴリゴリに書く人で、.Netってな~に?って状態ですので、間違ってても責任取りません。
ってかむしろこういう方法あるよ!、みたいな素敵な指摘が欲しいです。
内容としては ListView header幅固定 を C++/CLIにwin32APIを混ぜて実現したもの
ちなみにヘッダの境界線にマウスが来た際にマウスカーソルが変更されるのも阻止。
まとめると
- ListViewのヘッダ幅がマウスで弄れないこと
- ヘッダの境界線上でマウスカーソルが変わらないこと
開発はVS2008 standerd sp1
家での確認は 7 pro のVC++ 2008 Express Edition
スゲー簡単な方法
// stdafx.hに追加 #include "windows.h" #include "commctrl.h" // Form1.hの適当なところに追加 // 略 EnableWindow( ListView_GetHeader( reinterpret_cast(this->listView1->Handle.ToInt32()) ), FALSE); // 略
ぶっちゃけ、
Google先生に「ListView ヘッダ固定」で聞いてTOPに返ってくる内容ですが…。
上記内容をフォームのコンストラクタの中にでも突っ込んでおけばOK。
その辺から拾ってきたのを足しただけですので、ありなのかどうかすら分かりませんが、一応目的は果たせます。
windows form アプリ的にはあまりwin32APIを使用されたくなさそうです。
環境にもよりますが、多分上記はまずリンカエラーとなるでしょう。
これもググれば答えが返ってきますが、一応方法を。
vs2008 standerd sp1 の場合は、うろ覚えですが、
・プロジェクト → プロパティ → C/C++ → 全般 → 追加のインクルードなんたら → 親からなんたら にチェック
で通るようになるかと。
何でも2005位からformアプリ作成時の初期設定では、win32用のライブラリが軒並み外されているとかで、自分で設定が必要らしいです。
もちろん個別に必要なライブラリをリンクしてもいいんですけど。
VC++ 2008 Express Edition
上記と同じ方法で行けると思いきや、駄目でした。
そこで取った方法は次の方法。
- Win32コンソールアプリを作成
- プロジェクト → プロパティ → リンカ → コマンドライン からlibファイル名をコピー
- Formアプリの同じ場所にコピーした内容を貼付け
ちなみにコピーした内容はこれ
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
不要なものも居るけどその辺は無視。
お作法的にいいのかどうかは全く分かりませんが、上記にたどり着いて気がついたのは
「余裕でwin32APIガンガン使えるじゃん!」ってことです。
ウィンドウハンドル取得できれば結構やりたい放題ですよね。
さて、上記のようにHeaderを無効化することで目的を果たすと、楽は楽なのですがこんな要望が来たらアウト。
・ヘッダ部分のクリックはしたい!
更に、私が確認した環境では上記方法ではヘッダ部分をクリックすると、何故か一行目のアイテムがクリックされたと認識することも発覚。
というわけで、ListViewもヘッダ部分もサブクラス化してしまへ。
//**************** // Form1.hとか //**************** HWND hList = reinterpret_cast(this->listView1->Handle.ToInt32()); HWND hHeader = ListView_GetHeader( hList); OrgList = (WNDPROC)GetWindowLongPtr( hList, GWLP_WNDPROC); SetWindowLongPtr( hList, GWLP_WNDPROC, (LONG_PTR)ListViewSubWindowProc); OrgListHeader = (WNDPROC)GetWindowLongPtr( hHeader, GWLP_WNDPROC); SetWindowLongPtr( hHeader, GWLP_WNDPROC, (LONG_PTR)ListViewHeaderSubWindowProc); //**************** // hoge.cpp/h 色々略 //**************** WNDPROC OrgList, OrgListHeader; LRESULT CALLBACK ListViewHeaderSubWindowProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch(msg){ case WM_SETCURSOR: return TRUE; } return (CallWindowProc(OrgListHeader, hWnd, msg, wp, lp)); } LRESULT CALLBACK ListViewSubWindowProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { NMHEADER* pnmhdr; switch(msg){ case WM_NOTIFY: pnmhdr = (NMHEADER*)lp; switch(pnmhdr->hdr.code){ case HDN_ENDTRACK: case HDN_BEGINTRACK: case HDN_TRACK: case HDN_DIVIDERDBLCLICKW: return TRUE; } break; } return (CallWindowProc(OrgList, hWnd, msg, wp, lp)); }
上記のソースもその辺探せば幾らでも出てきます。
- Header部分でカーソルを変更させない
- カラム幅をいじらせない
ちなみにヘッダをクリックできるとか出来ないとかは、ListView::HeaderStyleで変更出来ますので、 まあ、わざわざwin32APIを使用するまででもないでしょう。
なお、恐らくこの段階ではまたもエラーになると思います。
コンパイル時に「 /clr:pure または /clr:safe と共にコンパイルされた関数に対する呼び出し規約 '__stdcall ' が無効です」というエラーがでると思います。
その指摘に従って
・プロジェクト → プロパティ → 共通言語ランタイム サポート
を /clr:pure から /clr へ変更することで、コンパイルが通るようになります。
また、Vistaから「HDS_NOSIZING」なるスタイルが追加されたようなのですが、
もしかするとこれらの実装(サブクラス化)をしなくても、このスタイル設定一発で終わる可能性も大ですね。
ま、めんどくて確認していませんし、そもそも私の場合XPで動作することが前提ですから。
誰か結果を教えてください。
ってか、こんな実装ありなんだろうか…
ぶっちゃけ何処がC++/CLIなんだか、普通にwin32じゃん…
C++/CLI 使いの方教えてください。
むしろ一番目に書くべきな気もしますが、貼り付けたコンソールのウィンドウハンドルって結構簡単に取れるよ!ってことが言いたいだけです。
0 件のコメント:
コメントを投稿