News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

How to capture keystrokes in a window with a read-only edit control

Started by NoCforMe, March 09, 2024, 03:14:24 PM

Previous topic - Next topic

NoCforMe

Here's a problem for y'all:

Let's say a guy has a window which contains a read-only edit control that occupies the entire window. (The purpose of this window is to display the text of a file.) This part works fine.

Let's say further that this guy would like to be able to search text within the window. To do so he wants to be able to use the Ctrl-F (or F3) keystrokes to initiate the search operation.

Problem is that because the edit control is read-only, any keystrokes only cause the system to ding at the user, which is the expected behavior of a read-only edit control.

Is there any way for this window (either the containing window or its child edit control) to receive the keystroke notification (WM_CHAR or similar)? I naively tried using SetFocus() on the edit control, but that doesn't work.

I'm not going to post any code for this question. (My code is very complicated.) Let's keep this at a theoretical level for now.

And no, I'd rather not implement a menu for this window, even though that would solve the problem (by having a "Find" item in it). I'd rather use the hotkey approach, if it's possible.
Assembly language programming should be fun. That's why I do it.


NoCforMe

Yes, I know about keyboard accelerators, use them in the surrounding code, but they don't work here (because of the read-only thing).

Subclassing? Hmm; worth a try, I guess. The key rejection takes place within the control's default processing code (within Win32), so keystrokes should be capture-able in the subclass routine before they get there.

However: If I try to SetFocus() on the (subclassed) edit control, won't that fail because the control is read-only? (I'll need to do that, otherwise keystrokes will go to the other edit control which is my editor's main edit window.)
Assembly language programming should be fun. That's why I do it.

NoCforMe

Aha, I may have hit on it. Thinking a bit more outside the box, how about if I don't make the edit control read-only, but subclass it and capture all keystrokes sent to it. Then I can just filter out the ones I want (Ctrl-F & F3) and use those to trigger my search. Since no keystrokes can get to the actual control, it will effectively be read-only.

What do you think about that?
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: sinsi on March 09, 2024, 03:37:35 PMAbout Keyboard Accelerators
Or subclass the edit control?

Accelerators work, see attachment, subclassing doesn't because the disabled window receives zero messages.

GuiParas equ "Disabled window", w500, h900, icon Butterfly
include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl MyEdit, "Edit", FileRead$("\Masm32\examples\exampl07\slickhuh\slickhuh.asm"),\
    font -14, +WS_DISABLED
  SetAccels F3:1
Event Accel
  MsgBox 0, Cat$('You want to find "'+Prompt$("Find:", "macros are evil")+'"'), "Hi", MB_OK
GuiEnd

sinsi

Quote from: jj2007 on March 09, 2024, 09:36:14 PMAccelerators work, see attachment, subclassing doesn't because the disabled window receives zero messages.
I thought read-only was different to disabled?
In another language I use you can still hilight and copy text from a read-only textbox.

sinsi

Back to the OP, doesn't an accelerator get passed to the main window proc and not the edit control?
The edit control is really just something that doesn't directly participate in the process.
The main window gets a WM_COMMAND to tell it that F3 was pressed, it then pops up a dialog asking what to search for, then searches the text in the edit control, the edit is just a bystander having their insides rummaged through by an outsider.

jj2007

Quote from: sinsi on March 09, 2024, 09:40:34 PMI thought read-only was different to disabled?

Correct, if you use ES_READONLY instead of WS_DISABLED, subclassing is an option. Besides, you can SetFocus an ES_READONLY control, and it will receive WM_CHAR etc messages :thumbsup:

NoCforMe

Could someone please address my idea in this post? Nobody's said anything about it yet.
Assembly language programming should be fun. That's why I do it.

jj2007


NoCforMe

OK, I am doing so as I type. Just thought someone would have a thought or two. No biggie.

OK, 1st test done. Not good: I was able to capture Alt-F in my subclassed edit control proc, but not Ctrl-F. And the reason is that I do have a keyboard accelerator for that keystroke which takes precedence, so I get the expected behavior of the accel. (opens a Find dialog but for the main edit window, not my subclassed one). Which means, I guess, that I'd have to get rid of the accelerator to make this scheme work.

Unless someone has some other ideas ...

One complicated, kluge-y idea: Set a flag in the subclassed edit proc when it becomes "activated" (meaning user clicks on it), use that flag in the main proc. where the hotkey sends that acclerator. If that happens, send a private message to the subclassed edit proc telling it to do a search THERE instead of the main window.

Ugh. Messy.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on March 10, 2024, 07:46:43 AMopens a Find dialog but for the main edit window

Check the hwndOwner member of FINDREPLACE (assuming you use FindText). Besides, what is the problem searching inside hEdit instead of hMain?

NoCforMe

Welll, it's complicated:
  • Main edit window is a RichEdit, "extra file view" windows are just edits.
  • Meaning that within the extra file windows, I have to implement my own search routine (can't use RichEdit search functions).
Hmm, would that be fixed by making the "extra file view" windows RichEdits also?

Not sure what you mean by FindText. Is that a function? message (EM_FINDTEXT)? what?
And who uses FINDREPLACE?
Assembly language programming should be fun. That's why I do it.

NoCforMe

Another part of what I need to do here: find a reliable way to determine when a window (in this case an edit control) becomes "active", meaning the user clicks into it.

I've captured the messages received by my "extra file view" edit control upon mousing over the window and clicking on it:
(on move mouse over window)
Message: WM_SETCURSOR    hWin: 20406h, wParam: 20406h, lParam: 2000002h
Message: WM_NCMOUSEMOVE    hWin: 20406h, wParam: 2h, lParam: 1E100AEh
Message: WM_SETCURSOR    hWin: 20406h, wParam: 20406h, lParam: 2000002h
Message: WM_NCMOUSEMOVE    hWin: 20406h, wParam: 2h, lParam: 1ED00AEh
Message: WM_NCACTIVATE    hWin: 20406h, wParam: 1h, lParam: 403FEh
Message: WM_ACTIVATE    hWin: 20406h, wParam: 1h, lParam: 403FEh
Message: WM_IME_SETCONTEXT    hWin: 20406h, wParam: 1h, lParam: C000000Fh
Message: WM_IME_NOTIFY    hWin: 20406h, wParam: 2h, lParam: 0h
Message: WM_SETFOCUS    hWin: 20406h, wParam: 403FEh, lParam: 0h
Message: WM_KILLFOCUS    hWin: 20406h, wParam: C0018h, lParam: 0h
Message: WM_IME_SETCONTEXT    hWin: 20406h, wParam: 0h, lParam: C000000Fh
Message: WM_COMMAND    hWin: 20406h, sending ID: 1400, notification code: 256
Message: WM_NCMOUSELEAVE    hWin: 20406h, wParam: 0h, lParam: 0h

(on clicking on window)
Message: WM_SETCURSOR    hWin: 20406h, wParam: 20406h, lParam: 2000002h
Message: WM_NCMOUSEMOVE    hWin: 20406h, wParam: 2h, lParam: 1E300B8h
Message: WM_NCMOUSELEAVE    hWin: 20406h, wParam: 0h, lParam: 0h
Message: WM_NCACTIVATE    hWin: 20406h, wParam: 0h, lParam: 403FEh
Message: WM_ACTIVATE    hWin: 20406h, wParam: 0h, lParam: 403FEh
Message: WM_COMMAND    hWin: 20406h, sending ID: 1400, notification code: 512
It looks as if WM_SETCURSOR is my friend here, yes? Or should I use WM_ACTIVATE (wParam = 0) instead?
Assembly language programming should be fun. That's why I do it.

jj2007