【VC++】SetROP2を使用して十字線カーソルを実装する
<機能>
(1)画面上に長い十字線カーソルを表示します
(2)画面上をダブルクリックするとポイント座標を表示します
※サンプルのためOnLButtonDblClkで表示しています
※再描画するためにはWM_PAINTで描画する必要があります
<動作検証&開発環境>
Visual Studio Community 2015
<イメージ>
画面上に十字線カーソルが表示されます
ダブルクリックするとポイント座標を表示します
<使い方>
(1)CrossCursorプロジェクトを作成
(2)シングルドキュメント(SDK)、MFC標準を選択
(3)システムメニュー以外のチェックを外す
(閉じるボタン「X」のみ表示する)
(4)本サンプルでは使用しない機能を外す
(5)クラスウィザードにてDrawCrossLineメンバ関数を追加
名前:DrawCrossLine
戻り値:void
パラメータ:CPoint cp
(6)メッセージハンドラを追加
・WM_LBUTTONDBLCLK(ダブルクリックイベント)
・WM_MOUSEMOVE(マウス移動イベント)
・WM_SETCURSOR(カーソルセット)
(7)ソースの追加
/* CrossCursorView.h */
private:
CPoint oldpo; //十字線の古いポイント位置を保持するための変数
/* CrossCursorView.cpp */
/*************************************************
関数名 DrawCrossLine
機能 カーソルのポイント位置より十字線(縦線+横線)を表示します
*************************************************/
void CCrossCursorView::DrawCrossLine(CPoint po)
{
RECT rect;
HWND hWnd = (HWND)this->GetSafeHwnd();
HDC hdc = ::GetDC(hWnd);
//描画できるクライアント領域を取得
::GetClientRect(hWnd, &rect);
//前景の描画モードを設定(色を反転させる)
//SetROP2についてはMSDNを参照してください
SetROP2(hdc, R2_NOT);
//縦線を描画
MoveToEx(hdc, po.x, 0, NULL);
LineTo(hdc, po.x, rect.bottom);
//横線を描画
MoveToEx(hdc, 0, po.y, NULL);
LineTo(hdc, rect.right, po.y);
//デバイスコンテキストを開放
::ReleaseDC(hWnd, hdc);
}
/*************************************************
関数名 OnLButtonDblClk
機能 ダブルクリックによりポイント座標を表示します
※実際の描画はWM_PAINTで行う必要があります(再描画されないため)
*************************************************/
void CCrossCursorView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
HWND hWnd = (HWND)this->GetSafeHwnd();
HDC hdc = ::GetDC(hWnd);
HPEN pen, oldpen;
//表示する文字列を生成
TCHAR tcstr[255];
ZeroMemory(&tcstr, sizeof(tcstr));
wsprintf(tcstr, L"(%d,%d)", point.x, point.y);
//緑のペン
pen = CreatePen(PS_SOLID, 5, RGB(0, 255, 0));
oldpen = (HPEN)SelectObject(hdc, pen);
//十字線を消去
DrawCrossLine(point);
//ポイント位置を中心に円を描画
Ellipse(hdc, point.x - 10, point.y - 10, point.x + 10, point.y + 10);
//ポイント位置を左上座標として文字列を描画
SetTextColor(hdc, RGB(255, 0, 0));
TextOut(hdc, point.x, point.y, tcstr, lstrlen(tcstr));
DrawCrossLine(point);
//ペンを戻す
SelectObject(hdc, oldpen);
//デバイスコンテキストを開放
::ReleaseDC(hWnd, hdc);
//ペンオブジェクトを開放
DeleteObject(pen);
}
/*************************************************
関数名 OnMouseMove
機能 マウスの動きに合わせて十字線を表示します
*************************************************/
void CCrossCursorView::OnMouseMove(UINT nFlags, CPoint point)
{
CClientDC dc(this);
//古い十字線を消去
DrawCrossLine(oldpo);
//現在位置の十字線を描画
DrawCrossLine(point);
//現在位置を保持
oldpo = point;
}
/*************************************************
関数名 OnSetCursor
機能 デフォルトのカーソルを4方向矢印(IDC_SIZEALL)に設定します
*************************************************/
BOOL CCrossCursorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
//カーソルの種類についてはMSDNを参照してください
//ウェイトカーソル
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
//ウェイトカーソル&矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_APPSTARTING));
//クロスカーソル
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
//4方向矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
//斜め左下がり矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW));
//斜め右下がり矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE));
//上下両方向矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS));
//左右両方向矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
//上矢印
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_UPARROW));
//アイビーム
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_IBEAM));
//禁止
//::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));
//4方向十字カーソルを選択
::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL));
return TRUE;
}
よろしければポチッと押してください