リストビューのカラムヘッダのMouseMove – プログラミング – Home

リストビューのカラムヘッダのMouse...
 
通知
すべてクリア

[解決済] リストビューのカラムヘッダのMouseMove

固定ページ 1 / 2

アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

現在VS2005 CLI環境で開発しております。

リストビューのヘッダの項目にマウスを動かしたときに、
マウス上の項目名を取得したいのですが、
MouseMoveイベントがヘッダ上だと発生しません。

ヘッダのMouseMoveイベントを取得したい場合、
どのような事をすればよいのでしょうか?

何かわかる方がいましたら、
ご教授していただけませんでしょうか?

宜しくお願いいたします。


引用未解決
トピックタグ
アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

WndProcを利用すればよいかと思い、

virtual void WndProc(Message% m) override
{
switch(m.Msg) {
case WM_MOUSEMOVE:
{
__super::WndProc(m);

pt = Cursor->Position;
pp = listView_StatusNoAuth->PointToClient(pt);
if ((0<= pp.X) && ( 0 <= pp.Y)) {
      やりたい処理
}

return;
}
__super::WndProc(m);
}

としたのですが、マウスがフォームの直下にあるときは呼ばれるのですが、
肝心のリストビューに入ったときは呼ばれずにダメでした。

なので、今度はWM_NCMOUSEMOVEで試したのですが、
ウインドウの枠から外れたときだけで、リストビューに入ったときは呼ばれませんでした。

リストビューのカラムヘッダ上にあるMouseMoveイベントは、
取る方法がないということなのでしょうか?


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

1、System::Windows::Forms::NativeWindow から派生したクラス(A)で WndProc() を
override
2、(A)::WndProc() にやりたい事書く
3、適当なタイミング(フォームload時等)で
 (A)->AssignHandle((System::IntPtr)::SendMessage(
  reinterpret_cast<HWND>((リストビュー)->Handle.ToInt32()), LVM_GETHEADER,
0, 0));


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

やってみたわけではないので、全く自信はありませんが、
CListCtrl::GetHeaderCtrl()
の戻り値を
CHeaderCtrl
の派生クラスでAttach()して、その派生クラスに
WM_MOUSEMOVE
のハンドラを用意してみてはいかがでしょう。

はずしてたらスイマセン。


返信引用
アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

gakさん、bunさん、情報ありがとうございます。

取り掛かりの道がまったくみえていなかったので、
これらの情報はとてもありがたいです。

あまり経験がないので時間がかかるかもしれませんが、
これから、これらの情報を元に試してみます。


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

> あまり経験がないので時間がかかるかもしれませんが、
という事なので一言助言。
俺とbunさんの書いている内容は基本的に同じ。.netクラスライブラリを使うかMFCを使う
かの違いだけです。

> CHeaderCtrl
> の派生クラスでAttach()して、その派生クラスに
ウィンドウプロシージャを置き換えなきゃいけないんで Attach() では無く
SubclassWindow()
ですね。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

gakさん、アレンさん、どうもです。

よく見たら、VS2005 CLI環境とありましたね。
MFCの例を載せてしまって失礼しました。


返信引用
アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

Form上でNativeWindowのクラスは定義できるのですが、
gcnewやAssignしようとすると

規定のコンストラクタがありません
認識できない型が使われてます

のメッセージがでてコンパイルできません。
なぜでしょうか?

以下ソース抜粋

namespace XXX {

using namespace System;
いろいろ定義
ref class NewNativeWindow;

public ref class Form1 : public System::Windows::Forms::Form
{
private:
NewNativeWindow^ NaWin;//これだけならコンパイルできる。

Form1(void) {
NaWin = gcnew NewNativeWindow(this); // 通らない
}

private: System::Void Form1_Load(System::Object^ sender,
System::EventArgs^ e) {

NaWin->AssignHandle((System::IntPtr)::SendMessage
(reinterpret_cast<HWND>(listView_StatusNoAuth->Handle.ToInt32()),
LVM_GETHEADER, 0, 0)); //通らない

}
};

/********* NativeWindow ***********/

ref class NewNativeWindow: public NativeWindow
{
Form1 ^frmParent;

public:
NewNativeWindow(Form1 ^parent) {

frmParent->HandleCreated += gcnew EventHandler( this,
&NewNativeWindow::OnHandleCreated );

frmParent->HandleDestroyed += gcnew EventHandler( this,
&NewNativeWindow::OnHandleDestroyed );

this->frmParent = parent;

}

internal:
void OnHandleCreated( Object^ sender, EventArgs^ /*e*/ ) {
AssignHandle( (dynamic_cast<Form1^>(sender))->Handle);
}

void OnHandleDestroyed(Object^ sender, EventArgs^ /*e*/) {
ReleaseHandle();
}

protected:
virtual void WndProc(Message% m) override {
やりたいこと
}
};
}


返信引用
K
 K
(@K)
ゲスト
結合: 23年前
投稿: 98
 

NewNativeWindowはForm1より前に定義されていますか?
コンストラクタやメソッドを呼び出しているので、
ref class NewNativeWindow;
だけでは不十分です。


返信引用
アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

単純にNewNativeWindowをForm1より前にもってくると、
今度はForm1が定義されていないとなってしまったので四苦八苦しましたが、
以下のようにしたらコンパイルは通りました。

ただ、リストビューのヘッダのMOUSE_MOVEは相変わらず発生しないようです。

namespace XXX {

using namespace System;
いろいろ定義
ref class NewNativeWindow;

public ref class Form1 : public System::Windows::Forms::Form
{
private:
NewNativeWindow^ NaWin;

private: System::Void Form1_Load(System::Object^ sender,
System::EventArgs^ e); // ここは定義だけ

};

/********* NativeWindow ***********/

ref class NewNativeWindow: public NativeWindow
{
Form1 ^frmParent;

public:
NewNativeWindow(Form1 ^parent) {

parent->HandleCreated += gcnew EventHandler( this,
&NewNativeWindow::OnHandleCreated );

parent->HandleDestroyed += gcnew EventHandler( this,
&NewNativeWindow::OnHandleDestroyed );

this->frmParent = parent;

}

internal:
void OnHandleCreated( Object^ sender, EventArgs^ /*e*/ ) {
AssignHandle( (dynamic_cast<Form1^>(sender))->Handle);
}

void OnHandleDestroyed(Object^ sender, EventArgs^ /*e*/) {
ReleaseHandle();
}

protected:
virtual void WndProc(Message% m) override {

switch(m.Msg) {
case WM_MOUSEMOVE:
{
__super::WndProc(m); // リストビューのヘッダでマウスを動かしてもこ
ない
pt = frmParent->Cursor->Position; // マウスの場所特定
pp = frmParent->listView->PointToClient(pt); // リストビューの位
置に変換

やりたいこと

}

}
};

/*** NewNativeWindowクラスを呼んでいるのは後で定義 ***/

System::Void Form1::Form1_Load(System::Object^ sender,
System::EventArgs^ e) {

NaWin = gcnew NewNativeWindow(this); // 通る
NaWin->AssignHandle((System::IntPtr)::SendMessage
(reinterpret_cast<HWND>(listView->Handle.ToInt32()),
LVM_GETHEADER, 0, 0)); //通る

}
}


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

ソース示した方が楽そうなので関連する部分の必用最低限のソース出す。
--------------------------------
ref class NewNativeWindow: public NativeWindow
{
protected: virtual void WndProc(Message% m) override {
やりたいこと
}
};

public ref class Form1 : public System::Windows::Forms::Form
{
private:
NewNativeWindow^ NaWin;
private:
System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
NaWin = gcnew NewNativeWindow();
// NewNativeWindowにリストビューのヘッダを割り当てる
NaWin->AssignHandle(
// Win32APIのSendMessage()を利用してリストビューのヘッダの
// ウィンドウハンドルを得る
(System::IntPtr)::SendMessage(
(HWND)(listView->Handle.ToInt32()),
LVM_GETHEADER, 0, 0
)
);
}
};
--------------------------------

> ただ、リストビューのヘッダのMOUSE_MOVEは相変わらず発生しないようです。
NewNativeWindowにはリストビューのヘッダをassignしないといけないが、提示ソースで
はそうならないから。
> void OnHandleCreated( Object^ sender, EventArgs^ /*e*/ ) {
> AssignHandle( (dynamic_cast<Form1^>(sender))->Handle);
> }
によって最初にForm1がNewNativeWindowにassignされる。
なので Form1::Form1_Load() の段階でリストビューのヘッダをassignしようとしても×。
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.nativewindow.assignhandle(VS.80).aspx


返信引用
アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

OnHandleCreated,OnHandleDestroyedを削除して、
リストビューのヘッダをassignするようにしたのですが、
やはり、ヘッダ上でマウスを動かしてもMOUSEMOVEイベントがこないようです。

namespace XXX {

using namespace System;
いろいろ定義
ref class NewNativeWindow;

public ref class Form1 : public System::Windows::Forms::Form
{
private:
NewNativeWindow^ NaWin;

private: System::Void Form1_Load(System::Object^ sender,
System::EventArgs^ e); // ここは定義だけ

};

/********* NativeWindow ********/

ref class NewNativeWindow: public NativeWindow
{
Form1 ^frmParent;

public:
void Setting(Form1 ^parent) {
this->frmParent = parent;
}

protected:
virtual void WndProc(Message% m) override {

switch(m.Msg) {
case WM_MOUSEMOVE:
{
__super::WndProc(m); // リストビューのヘッダでマウスを動かしてもこ
ない
pt = frmParent->Cursor->Position; // マウスの場所特定
pp = frmParent->listView->PointToClient(pt); // リストビューの位
置に変換

やりたいこと

}

}
};

/ NewNativeWindowクラスを呼んでいるのは後で定義 ***/

System::Void Form1::Form1_Load(System::Object^ sender,
System::EventArgs^ e) {

NaWin = gcnew NewNativeWindow(); // 通る
NaWin->AssignHandle(
        (System::IntPtr)::SendMessage(
         reinterpret_cast<HWND>(listView->Handle.ToInt32()),
         LVM_GETHEADER, 0, 0)); //通る

NaWin->Setting(this);

}
}


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

わからんなぁ。
提示ソースの WndProc(Message% m) では WM_MOUSEMOVE がきた時しか
__super::WndProc(m); を呼んでいない点が気になるといえば気になるけど…2008/04/10
(木) 13:28:56 投稿のソースだと呼んでいるので今回掲示を省略しただけポイしなぁ。

・Win32API ::SendMessage() でヘッダのウィンドウハンドルの取得に成功しているか
・NaWin->AssignHandle() は成功しているか
・WndProc() そのものは呼ばれているか
・WndProc() は処理されているが WM_MOUSEMOVE メッセージだけ捕まえられないのか
・新規プロジェクトを作成して必要最低限のコードのみを組み込んだexeで試しても×か

とりあえず上記点を潰した後でも問題点が露見しないようなら別手段を模索すべきかと。
ただ俺の環境ではxp、vista(共に.net2.0sp1)で期待通りの動作を確認できたから無理
ではないと思うが


返信引用
gak
 gak
(@gak)
ゲスト
結合: 21年前
投稿: 132
 

この方法はWin32APIが使えない環境では当然ダメですよ。
改めて書くまでもないと思うけど。


返信引用
アレン
 アレン
(@アレン)
ゲスト
結合: 17年前
投稿: 18
Topic starter  

>・Win32API ::SendMessage() でヘッダのウィンドウハンドルの取得に成功しているか

値が入っていましたので大丈夫かと思います。

>・NaWin->AssignHandle() は成功しているか

NaWin->AssignHandleに対して
try catchで例外が発生が発生していないようなので成功していると思います。

>・WndProc() そのものは呼ばれているか

フォームが作成されるときに、WndProc自体は呼ばれているようです。

>・WndProc() は処理されているが WM_MOUSEMOVE メッセージだけ捕まえられないのか

上記のことからWM_MOUSEMOVEメッセージだけ捕まえられないようです。

>・新規プロジェクトを作成して必要最低限のコードのみを組み込んだexeで試しても×か

最低限のコードで試したところうまくいきました。
なので、アプリ内で何かしてしまっているのだと思います。

あとは、一つ一つ追っていこうと思います。

というわけで、本件は一旦解決としておきます。

gakさんにはとてもお世話になりました。
本当にありがとうございました。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました