
Win32APIの習作としてエディタを作っているのですが,
ステータスバーに現在のキャレット位置を表示する部分で困っています.
いろいろ調べて下記のコードを書いてみたのですが,
エディットコントロールに更新が無いとき(矢印キーで移動など)
にキャレット位置の更新ができないです.
良い方法がありましたらご教授下さい.
(ここのサンプルコードが良いとかでもありましたらお願いします.)
////////////////////////////////////////////////////////////////
// MyEditor.c
static const int FONT_WIDTH = 6;
static const int FONT_HEIGHT = 18;
int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
...略...
}
LRESULT __stdcall WndProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp)
{
...略...
switch (uMsg) {
...略...
case IDC_EDIT:{
char str[64];
POINT pt = {0, 0};
RECT rc = {0, 0, 0, 0};
GetCaretPos(&pt);
wsprintf(str, "現在のキャレット位置 (%d, %d)",
pt.x / FONT_WIDTH, pt.y / FONT_HEIGHT);
SendMessage(hStatusbar, SB_SETTEXT, 1, (LPARAM)str);
GetClientRect(hStatusbar,&rc);
InvalidateRect(hStatusbar, &rc, TRUE);
break ;}
...略...
}
return 0L;
}
No.1ベストアンサー
- 回答日時:
★アドバイス
・エディット・ボックスをサブクラス化してWM_KEYDOWNで
カーソルキーの移動を監視。移動されていればキャレット位置の
表示をすれば良いでしょう。
http://wisdom.sakura.ne.jp/system/winapi/win32/w …→『サブクラス化』
http://wisdom.sakura.ne.jp/system/winapi/win32/w …→『キーボードイベント』
アドバイスありがとうございます.
リンクを参考に下記のように変更し,
ひとまず目的を達成できました.
しかし, 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;
}
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 );
}
こんな感じでどうでしょうか。
※インデントは全角空白を使っています。
この回答への補足
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;}
※インデントに全角スペースを使いました.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CTreeCtrlのCreate関数でエラー...
-
Win32APIでウィンドウを中央に...
-
音量調節
-
Aの値からBの値を除するとは??
-
「Aに対するBの割合」と「Aに対...
-
複数桁10進数の*桁目だけを抽出...
-
2÷3などの余りについて
-
Enterキーを押されたら次の処理...
-
「指定されたキャストは有効で...
-
エクセルで可視セルにのみ値貼...
-
*をユーザーが入力した数字の数...
-
C言語の勉強しています。すみま...
-
C言語での引数の省略方法
-
構文エラー";"が型の前にあり...
-
DWORDの実際の型は何でしょうか
-
#define _CRT_SECURE_NO_WARNIN...
-
信頼区間の1.96や1.65ってどこ...
-
プログラム
-
c言語のプログラミングについて...
-
プログラムでの数字につく”f”の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エディットボックスの背景の色...
-
エラー Run-Time Check Failur...
-
C#のswitch文を簡略化したいの...
-
プログラミングでエラーが出ま...
-
Win32APIでウィンドウを中央に...
-
Unicode でのWin32アプリのプロ...
-
c言語初心者です。ついに。。
-
LoadImageを使用し、タイトルバ...
-
AVRによるマトリクスLED制御
-
オーバーレイみたいな処理がしたい
-
MessageBoxについて
-
ダイアログプログラムでEnterキ...
-
Win32 APIでのVirtual-Key Co...
-
Win32のファイルダイアログのサ...
-
キャレットの現在位置の表示 (W...
-
C言語です
-
ボタンの色(WINAPI)
-
WinAPIでの画像高速切り替え表...
-
WM_KEYDOWNでPrtScを捕まえる方...
-
ウィンドウサイズを変更しても...
おすすめ情報