マウスカーソルの変更

解決


まさ  2003-12-04 13:02:24  No: 52750  IP: [192.*.*.*]

マウスカーソルを虫眼鏡に変更したいのですが、
方法がわかりません。
アイコンを作成せずに変更させたいのですが
無理でしょうか?

BTTNCUR.Hに#define IDC_MAGNIFY 502というのが
あるのでどうにかすればできるのではないかと
考えているのですが・・・

ご存知の方がいらっしゃいましたらご教授ください。
よろしくお願い致します。

編集 削除
なーめ  2003-12-04 20:00:03  No: 52751  IP: [192.*.*.*]

IDC_MAGNIFY は MSDN のサンプルの中で定義されているカーソルで
システムに登録されているものではありません。
なので、
ヘルプ:
MSDN ライブラリ 2001年10月
 L VisualStudio6.0ドキュメント
   L Visual C++ ドキュメント
     L サンプル
       L SDK Samples
         L COM Samples
           L COM Application Samples
             L Bttncur: Buttons and Cursors

を開いて、Click to open or copy the Bttncur project files.
をクリックし、サンプルを読み込みます。
必要なのは この中の res\magnify.cur だけで、これを自分のプロジェクトの
中の、res にコピーし、import します。
でこのリソースのIDを IDC_MAGNIFY にしてやって、
CWnd 派生クラスのコンストラクタあたりで 
m_hCursor = LoadCursor( IDC_MAGNIFY );
ウィンドウが初期化されるあたりで、(ダイアログならOnInitDialog())
SetClassLong( m_hWnd, GCL_HCURSOR, (long)m_hCursor );
を行えばいいですね。
以下、ダイアログで使用する例です。
BTTNCUR.Hはインクルードしないでください。
IDC_MAGNIFY はインポート時に自分の resource.h に自動登録されるはずです。

CT04Dlg::CT04Dlg(CWnd* pParent /*=NULL*/)
  : CDialog(CT04Dlg::IDD, pParent)
{
  //{{AFX_DATA_INIT(CT04Dlg)
  //}}AFX_DATA_INIT
  m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
//  m_hCursor = AfxGetApp()->LoadCursor( IDC_CURSOR1 );
  m_hCursor = AfxGetApp()->LoadCursor( IDC_MAGNIFY );
}

BOOL CT04Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  ASSERT(IDM_ABOUTBOX < 0xF000);

  CMenu* pSysMenu = GetSystemMenu(FALSE);
  if (pSysMenu != NULL)
  {
    CString strAboutMenu;
    strAboutMenu.LoadString(IDS_ABOUTBOX);
    if (!strAboutMenu.IsEmpty())
    {
      pSysMenu->AppendMenu(MF_SEPARATOR);
      pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
  }
  SetIcon(m_hIcon, TRUE);
  SetIcon(m_hIcon, FALSE);
  SetClassLong( m_hWnd, GCL_HCURSOR, (long)m_hCursor );
  return TRUE;
}

### SetCursor() という関数にだまされませんでしたか?(^^;;


では。

編集 削除
YuO  2003-12-04 20:53:50  No: 52752  IP: [192.*.*.*]

カーソルの変更は,WM_SETCURSORに対する応答で行うのが基本です。
#MFCだとOnSetCursor

WM_SETCURSORに対する応答では,Hit Testの結果がHTCLIENTの時にDefWindowProc APIを呼び出すと,
カーソルはWNDCLASS::hCursorに設定されます。
ここでDefWindowProcを呼び出さずにSetCursor APIを呼び出せば,マウスカーソルは変更されます。
#非クライアント領域も扱うので注意が必要。

ただし,WM_SETCURSORではマウスの位置情報は取得できません。
位置情報が必要な場合は,WM_SETCURSORではSetCursorもDefWindowProcも呼び出さずに制御を返し,
WM_MOUSEMOVEでSetCursor APIを呼び出すことで,
位置情報を取得しつつカーソルを変化させることができます。
#WM_MOUSEMOVEで取得できるのはHTCLIENTのみ。

編集 削除
なーめ  2003-12-05 16:03:41  No: 52753  IP: [192.*.*.*]

OnSetCursor() でさっくり動かなかったんで、
変な方法を示して、すみません。

>> カーソルの変更は,WM_SETCURSORに対する応答で行うのが基本です。
OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
// TODO: この位置にメッセージ ハンドラ用のコードを追加するか
// またはデフォルトの処理を呼び出してください
  SetCursor( m_hCursor );
  return CDialog::OnSetCursor(pWnd, nHitTest, message);
}

これじゃ動かないはずですねー。
親クラス呼び出しを止めてませんでした。
return( TRUE ); でした。
大ボケでした。_(O)_

編集 削除
まさ  2003-12-08 20:21:36  No: 52754  IP: [192.*.*.*]

> IDC_MAGNIFY は MSDN のサンプルの中で定義されているカーソルで
> システムに登録されているものではありません。

確かに、VC++内のresフォルダ下にMAGNIFY.curがありました。
てっきりIDC_MAGNIFYを使って設定するのかと思ってました(^^;
ご回答誠にありがとうございました。

編集 削除
YuO  2004-03-02 20:40:06  No: 52755  IP: [192.*.*.*]

> 「WM_SETCURSORメッセージは、 マウス入力がキャプチャされていないときに、 
> ウィンドウ内でマウスを使用してカーソルを移動した場合に、 ウィンドウに
> 送られます。」と有ります。

その通りです。
前に挙げたMSDNにも,
>The WM_SETCURSOR message is sent to a window if the mouse causes the cursor to move within a window and mouse input is not captured.
と記述があります。


> これはクライアント領域に入ってくると解釈してますが?

なぜ,そのように解釈したのですか?
ウィンドウとクライアント領域は別物です。
そうであれば,to move within a client areaのように記述されると思われますが。


> 具体的なイメージは湧いてませんが、基本的に親ウィンドウで制御する上でのヒットテストなんだろうなと解釈してます。

ヒットテストというのがわかっていないようですね……。
http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/aboutmouseinput.asp#_win32_The_WM_NCHITTEST_Message
なんかは読んでみるとよいでしょう。

テストを行うのはシステムです。
そして,それによってシステムは指定した場所がどの領域(クライアント・キャプション・右の枠etc.)であるかを得ます。


> (YuOさんは、とあるクライアントウィンドウプロシージャでクライアント外にあるマウスカーソルをヒットテスト出来ると仰ってます?)

「クライアントウィンドウプロシージャ」とは一体なんですか?
ウィンドウプロシージャ自体はウィンドウに関連する全てのメッセージを取り扱います。

編集 削除
YuO  2004-03-02 20:40:40  No: 52756  IP: [192.*.*.*]

発言先を間違えました……。
#参照しながら書いていたので……。

編集 削除