• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:キャレットの現在位置の表示 (Win32API))

キャレットの現在位置の表示

このQ&Aのポイント
  • Win32APIの習作としてエディタを作っているのですが,ステータスバーに現在のキャレット位置を表示する部分で困っています.
  • エディットコントロールに更新が無いときにキャレット位置の更新ができないです.
  • 良い方法がありましたらご教授下さい.

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★アドバイス ・エディット・ボックスをサブクラス化してWM_KEYDOWNで  カーソルキーの移動を監視。移動されていればキャレット位置の  表示をすれば良いでしょう。  http://wisdom.sakura.ne.jp/system/winapi/win32/win64.html→『サブクラス化』  http://wisdom.sakura.ne.jp/system/winapi/win32/win30.html→『キーボードイベント』

H_Oka
質問者

お礼

 アドバイスありがとうございます. リンクを参考に下記のように変更し, ひとまず目的を達成できました. しかし, hStatusbar が, EditProc() 内で取得する方法がわからなかったため, グローバルになってしまいました. FindWindow() という関数で hStatusbar を取得しようと 思ったのですが,CreateStatusWindow() を使用しているので クラス名とウィンドウ名がわかりません. できればこれも解決法をお願いします. ハンドルを得る方法は他の場面でも重要になると思いますので. // MyEditor.c static HWND hStatusbar; int __stdcall WinMain(...){} LRESULT __stdcall EditProc(HWND hEdit, UINT uMsg, WPARAM wp, LPARAM lp) { switch (uMsg) { case WM_KEYDOWN: case WM_LBUTTONDOWN:{ char str[64] = {0}; POINT pt = {0, 0}; RECT rc = {0, 0, 0, 0}; GetCaretPos(&pt); wsprintf(str, "現在のキャレット位置 (%d, %d)",pt.y / FONT_HEIGHT, pt.x / FONT_WIDTH); SendMessage(hStatusbar, SB_SETTEXT, 1, (LPARAM)str); GetClientRect(hStatusbar, &rc); InvalidateRect(hStatusbar, &rc, TRUE); break;} } return CallWindowProc(DefEditProc, hEdit, uMsg, wp, lp); } LRESULT __stdcall WndProc(...) { ...略... switch (uMsg) { case WM_CREATE: GetClientRect(hWnd, &rc); hEdit = CreateMultilineEditWindow(hWnd, rc); // エディットウィンドウのサブクラス化 DefEditProc = (WNDPROC)GetWindowLong(hEdit, GWL_WNDPROC); SetWindowLong(hEdit, GWL_WNDPROC ,(LONG)EditProc); // コモンコントロール関係の初期化 InitCommonControls(); // ステータスバーを作成 hStatusbar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, "ステータスバー", hWnd, IDC_STATUS); SendMessage(hStatusbar, SB_SETPARTS, MY_SB_PART_COUNT, (LPARAM)rightEdgePosition); break; ...略... } return 0L; }

その他の回答 (1)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★アドバイス >ハンドルを得る方法は他の場面でも重要になると思いますので.  ↑  ハンドルを取得する方法よりもサブクラス化したEditProcから  親プロシージャにキャレット位置の変更を通知すれば楽です。 ・仕組みは  (1)EditProcでSendMessageを使いWM_APP+1などを送る  (2)親プロシージャでWM_APP+1を受け取る  (3)受け取ったときにステータスバーに位置を表示 サンプル: #define WM_MY_STATUSBAR (WM_APP + 1) LRESULT __stdcall WndProc(...) {  static HWND hStatusbar; ←ここに書く(ここでも良いかな?)    switch ( uMsg){   case WM_CREATE:    ...略...    // ステータスバーを作成    hStatusbar = CreateStatusWindow( …略… );    break;   case WM_MY_STATUSBAR:   {    char str[64];    POINT pt;    RECT rc;        GetCaretPos( &pt );    wsprintf(str, "現在のキャレット位置 (%d, %d)",pt.y / FONT_HEIGHT, pt.x / FONT_WIDTH);    SendMessage( hStatusbar, SB_SETTEXT, 1, (LPARAM)str );    GetClientRect( hStatusbar, &rc );    InvalidateRect( hStatusbar, &rc, TRUE );    break;   }  }  return 0L; } LRESULT __stdcall EditProc(HWND hEdit, UINT uMsg, WPARAM wp, LPARAM lp) {  switch ( uMsg ){   case WM_KEYDOWN:   case WM_LBUTTONDOWN:    SendMessage( GetParent(hEdit), WM_MY_STATUSBAR, 0, 0 );    break;  }  return CallWindowProc( DefEditProc, hEdit, uMsg, wp, lp ); } こんな感じでどうでしょうか。 ※インデントは全角空白を使っています。

H_Oka
質問者

お礼

ありがとうございます. 教えて頂いたおかげでウィンドウズの基本的な動きが 理解できてきました.

H_Oka
質問者

補足

 WM_MY_STATUSBAR を受け取った後のキャレット位置の表示処理ですが, フォント幅は文字に依存するため,定数 FONT_WIDTH で キャレットの クライアント座標 pt.x を割って求めるとずれてしまう問題が起きました. そこで,EM_CHARFROMPOS を使用して以下のように変更してみたのですが, y 方向のスクロールバーが動き出すあたりから pt.x の値が意図しない ものになってしまいます.2Byte ずつ増えているので,どこかで \r\n を拾っているのかもしれないです. できればアドバイスを頂けないでしょうか? case WM_MY_STATUSBAR:{   char str[64];   POINT pt = {0, 0};   RECT rc;   DWORD chPos;   GetCaretPos(&pt);   chPos = SendMessage(hEdit, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));   pt.y = HIWORD(chPos);   chPos = SendMessage(hEdit, EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, 0));   pt.x = LOWORD(chPos);   wsprintf(str, "現在のキャレット位置 (%d, %d)", pt.y, pt.x);   SendMessage(hStatusbar, SB_SETTEXT, 1, (LPARAM)str);   GetClientRect(hStatusbar,&rc);   InvalidateRect(hStatusbar, &rc, TRUE); break;} ※インデントに全角スペースを使いました.