2016-06-17 1 views
1

マウスが特定のコントロール上にあるときにカーソルを変更したい。私はカーソルのPNGを持っています。どのように私はC + +でそれを達成するのですか?マウスが特定のコントロール上にあるときにカスタムカーソルを設定するにはどうすればよいですか?

説明するように、私はhere

HCURSOR hcur; 
hcur = ::LoadCursorFromFile("cursor.png"); 
::SetSystemCursor(hcur,OCR_NORMAL); 

このようにしようとしたが、それはOCR_NORMALが定義されていないと言います。

HINSTANCE hInst;   
hInst = GetModuleHandle(NULL); 

HCURSOR hCurs;  
hCurs = LoadCursor(hInst, MAKEINTRESOURCE(2)); 

::SetSystemCursor(hCurs,OCR_NORMAL); 

私もそのようにしようとしたが、その生成奇妙なリンカエラーは次のように:

Error 2 error LNK2019: unresolved external symbol "extern "C" struct HICON__ * __stdcall LoadCursorW(struct HINSTANCE__ *,wchar_t const *)" ([email protected]@[email protected]@[email protected]@[email protected]) referenced in function "int __cdecl main(void)" ([email protected]@$$HYAHXZ) C:\Users\Diozz\Documents\Visual Studio 2013\Projects\Scroller\Scroller\main.obj 

私はその権利を期待して、プロジェクトディレクトリにPNGを配置することです。

どうすればカーソルを設定できますか?

+0

カーソルがボタン上にある場合にのみカスタムカーソルが必要ですか?または、カーソルをフォーム全体のカスタムなものにする必要がありますか? – Rakete1111

+0

@ Rakete1111。うん、そうだよ。正確には、ピクチャボックス。 (フォーム全体ではありません) –

+0

[this](http://stackoverflow.com/questions/10277966/how-to-change-the-cursor-on-a-button) – Rakete1111

答えて

2

カーソルが特定のコントロールの上にあるときにカーソルを変更する場合は、そのコントロールのウィンドウのメッセージを処理する必要があります。このメッセージを受信すると、SetCursor関数を呼び出して、表示すべきカーソルを設定します。この関数は、単一のパラメータ、つまりカーソルへのハンドル(HCURSOR)をとります。これに関する詳細については、Raymond Chenの記事を必ず読んでください。"What is the process by which the cursor gets set?"

SetSystemCursorの機能は一切使用しないでください。その機能は、のグローバルカーソル設定を変更する方法を提供します。マウスコントロールパネルで同じカーソル設定を変更することができます。デスクトップをカスタマイズしたい場合は、変更する必要があります。アプリケーションはそれだけを残すべきです。アプリケーションのコントロール上にファンキーなカーソルを表示したい場合は全く問題ありませんが、ではないシステム全体の矢印カーソルをファンキーなものに置き換えても問題ありません!

私たちは実際にSetSystemCursorを呼び出す正しい方法について心配する必要はありません。だから、カーソルの読み込みを見てみましょう。あなたは既にLoadCursorFromFile関数を見つけました。実際、この名前はその名前が示すとおりです。 CURファイルへのパスを与え、カーソルとしてハンドルを渡してカーソルを右にロードします(HCURSOR)。しかし、テストの目的以外では、LoadCursorFromFileを使用しているとは思わないでしょう。どうして?あなたのアプリケーションと一緒にCURファイルを配備する必要はないからです。そのファイルが削除されるか、含まれていない場合、アプリケーションは動作しなくなります。

代わりに、カーソルをアプリケーションのバイナリに直接リンクする必要があります。幸いにも、Windowsはバイナリのリソースの一部としてこれを行う方法を提供します。これまでにWindowsプログラミングをしたことがあるなら、あなたは確かにリソースファイルを見たことがあります。 RCファイルに、ICOファイルへのパスを指定するカーソルリソースを追加することができます。リソースコンパイラは残りの処理を行い、そのカーソルをEXEに直接埋め込みます。これで、実行時に脆弱なパスに頼る必要がなくなりました。LoadCursorを呼び出してリソースからカーソルをロードするだけです。 (すべてのリソースResource.hを呼ばれるヘッダ・ファイルに定義された数値IDを、与えられている。さんがあなたのID IDC_FUNKYを持っていると仮定しましょう。)

HINSTANCE hInstance = ::GetModuleHandle(NULL); // get a handle to the app's instance 
HCURSOR hCursor = ::LoadCursor(hInstance, MAKEINTRESOURCE(IDC_FUNKY)); 

は今、あなたのEXEに埋め込まれたリソースからあなたのファンキーなカーソルをロードしました。もちろん、LoadCursorを使用して、あらかじめ定義されたシステムカーソルをロードすることもできます。これを行うには、最初のパラメータにNULLを渡します。これは、アプリケーションのリソースからロードするのではなく、システムからロードするためです。たとえば、のは、ヘルプカーソルをロードしてみましょう:

HCURSOR hCursorHelp = ::LoadCursor(NULL, IDC_HELP); 

グレート-今、私たちは、カーソルをロードする方法を知っています。 1つのことを除くすべて:私たちが扱ったカスタムカーソルはすべてCUR(またはANI)ファイルとして保存されています。あなたはPNGファイルからカーソルをロードしたいという質問に言及します。正直なところ、私の提案はではなく、である。 PNGファイルをCURファイルに変換し、CURファイルを使用できるカーソル作成プログラムを使用します。それ以外の場合は、PNGファイルを読み込んでビットマップに変換し、そのビットマップをカーソルに変換する無意味なコードを書くことが忙しくなります。あなたが始めるとすぐにレンガの壁に当たるでしょう。 Win32 APIを使用してPNGイメージを読み込む明白な方法はありません。 GDI +、Windows Imaging Component、またはPNGファイルを処理できるサードパーティのライブラリを使用する必要があります。完全にこの答えの範囲外です。このウサギの穴を下りたい場合は、herehereを参照してください。それ以外の場合は、Greenfish Icon Editorのようなものをダウンロードして、変換を一度行い、あなたの人生に乗ってください。一緒にすべてを置く

は、それから、ここにあなたが何をすべきかです:

  1. は、あなたのPNGファイルは、ICOファイルに変換し、リソースとしてアプリケーションにこのICOファイルを追加します。これはVisual Studio内から簡単に実行できます。
  2. LoadCursor関数を呼び出して、リソースからカーソルをロードするコードを作成します。これはHCURSORです。初期化ルーチンで、アプリケーションを最初に起動するときにこれを行うのが賢明でしょう。返されたハンドルをキャッシュして、アプリケーションの存続期間全体にわたって使用できるようにします。コントロールがダイアログ上にある場合は、WM_INITDIALOGでこれを行うことができます。
  3. あなたのコントロールのためにWM_SETCURSORメッセージを処理してください。あなたがサブクラス化することでこれを行うことができますが、ほとんどの場合、それだけで親のウィンドウプロシージャにコードを配置するのが最も簡単です:

    static HCURSOR hCursorFunky; 
    
    ... 
    
    case WM_SETCURSOR: 
    { 
        // If we're the control that should get the cursor treatment... 
        if (static_cast<HWND>(wParam) == hwndYourControl) 
        { 
         ::SetCursor(hCursorFunky); 
         return TRUE; // indicate we processed this message 
        } 
        return ::DefWindowProc(hWnd, uMsg, wParam, lParam); // do default handling 
    } 
    

    または、ダイアログ内のコントロールの生活、わずかな変化の場合:

    case WM_SETCURSOR: 
    { 
        if (static_cast<HWND>(wParam) == ::GetDlgItem(hWnd, IDC_YOURCONTROL)) 
        { 
         ::SetCursor(hCursorFunky); 
         ::SetWindowLongPtr(hWnd, DWLP_MSGRESULT, TRUE); 
         return TRUE; // indicate we processed this message 
        } 
        return FALSE; // do default handling 
    } 
    

最後の注意:あなたが適切にどこのWindows SDKを見つけるために、リンカに語っていないことを示唆している、あなたの質問にリンカエラーを表示します。このビジネスはすべてVisual Studioの "Win32 Application"テンプレートによって自動的にセットアップされます。あなたはそれを使って新しいプロジェクトを作るべきです。もしそうでなければ、あなたのプロジェクトの設定に入り、リンカに(少なくとも)kernel32.lib,user32.lib、およびgdi32.libを使用するように指示する必要があります。そうしないと、リンカは呼び出しようとしているWindows API関数を見つけることができません。

+0

* "このメッセージを受け取ったら、表示する必要があるカーソルへのハンドルを返します" * - いいえ、カーソルへのハンドルは返されません。 'SetCursor'を返す前に呼び出す必要があります。 –

+0

@Cody Greyお世話になりました。これはきちんとした完全な答えですが、問題は依然として続きます。ビジュアルスタジオでリソースビューを見つけられず、カーソルをリソースとして追加する方法がわかりません。私はちょうど(私が使用する)エクスプレス版がこの機能を欠いていると考えました。ですから、カーソルを追加する方法はありますか、別のエディションに切り替える必要はありますか? –

+0

@jonathanありがとう、私はそこに何を考えていたのか分かりません。 2つの段落とサンプルコードで正しく理解しました。ハハ、ああ。私はその誤ったアサーションを削除する答えを更新しました。 –

関連する問題