hey al.
i'm working on a simple richtext editor
right now to get keydown i'm using wm_notify msg
than read the NMHDR struct
than the MSGFILTER struct
but i wonder why i don't get wm_keydown in the wndproc, only wm_notify
the problem with that is, i want to have control on the wm_keydown event
before the richtext knowks about it.
sometimes maybe i want to prevent the wm_keydown msg to be sent to the richedit control.
but it seemd that when the richtext control is in focus,
i don't get the wm_keydown msg,
the richtext get it,
and i only get wm_notify from the richtext, to notify me that there was a keydown.
so my question is:
- is there a way to get the wm_keydown msg before the richtext, without subclass it ?
I suspect the only way would be to have a global hook that intercepts all keyboard activity.
EDIT: Actually not a global hook, just a hook. SetWindowsHookEx() API
A subclass would be easier.
John
ok. thank you very much.
i also asked this in MSDN, if i'll get another answer,
i hope i won't forget to post it here :)
EDIT: i just tried to subclass, i do get the wm_keydown now,
but after the richtext get it.
i'm calling msgbox, when i get the keydown,
when i see the msgbox, i also see that the new key is already processed by the rtf control.
also when i get the keydown, i don't call the CallWindowProc function.
and i still can see the new key in the richtext control.
here is my code
int MsgBox (char *Msg, char *Title, int Num)
{
return MessageBox(GetActiveWindow(),Msg,Title,Num);
}
int WindowProc (HWND hWnd, int uMsg, int wParam, int lParam)
{
/* Select Case uMsg */
if(uMsg==WM_KEYDOWN)
{
MsgBox ("got key down :)","",0);
return 0;
}
return CallWindowProc((WNDPROC)PrevProc,hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR CmdLine, int CmdShow)
{
MSG Msg;
memset(&Msg,0,sizeof(Msg));
strcpy(AppName,"Editor_Demo");
strcpy(AppMenu,"IDMAINMENU");
strcpy(Caption,"Editor by Doyle Whisenant");
Wc.style=CS_HREDRAW BOR CS_VREDRAW;
Wc.lpfnWndProc=WndProc;
Wc.cbClsExtra=0;
Wc.cbWndExtra=0;
Wc.hInstance=hInst;
hInstance=hInst;
Wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
Wc.hCursor=LoadCursor(NULL,IDC_ARROW);
Wc.hbrBackground=CAST(HBRUSH,GetStockObject(WHITE_BRUSH));
Wc.lpszMenuName=AppMenu;
Wc.lpszClassName=AppName;
RegisterClass( &Wc);
Form1=CreateWindow(AppName,Caption,WS_CAPTION BOR WS_MAXIMIZEBOX BOR WS_MINIMIZEBOX BOR WS_SIZEBOX BOR WS_POPUP BOR WS_SYSMENU BOR WS_VISIBLE,0,0,600,500,NULL,(HMENU)NULL,hInst,NULL);
RE_hDll=LoadLibrary("RICHED20.DLL");
Edit1=CreateWindow(RICHEDIT_CLASS,NULL,WS_CHILD BOR WS_CLIPCHILDREN BOR WS_CLIPSIBLINGS BOR WS_VISIBLE BOR WS_BORDER BOR ES_LEFT BOR WS_HSCROLL BOR WS_VSCROLL BOR ES_MULTILINE BOR ES_AUTOVSCROLL BOR ES_AUTOHSCROLL,0,0,550,450,Form1,(HMENU)EDIT_1,hInst,NULL);
SetEditorOptions();
Edit1Font=MakeFont("Courier New",9);
SendMessage((HWND)Edit1,(UINT)WM_SETFONT,(WPARAM)Edit1Font,(LPARAM)0);
PosMainWindow(Form1);
ShowWindow(Form1,CmdShow);
UpdateWindow(Form1);
PrevProc=(WNDPROC) SetWindowLong((HWND)Edit1,GWL_WNDPROC,(LONG) &WindowProc);
while(GetMessage( &Msg,NULL,0,0))
{
TranslateMessage( &Msg);
DispatchMessage( &Msg);
}
if(PrevProc!=0)
{
SetWindowLong(Edit1,GWL_WNDPROC,CAST(int,PrevProc));
PrevProc=0;
}
if(RE_hDll)
{
FreeLibrary(RE_hDll);
}
return Msg.wParam;
}
I suggest that is not your code because it doesn't compile.
Anyway, this
PrevProc = (WNDPROC)SetWindowLong((HWND)Edit1, GWL_WNDPROC, (LONG) & WindowProc);
Will not work. What is "& WindowProc" meant to be?
John
i posted only part of it.
about your question, this is the address of WindowProc function.
and it works very well.
Ok, well it is best to post compile-able code so that anyone trying to help does not have to mess about trying to get things right.
EDIT:
Try trapping both WM_KEYDOWN and WM_CHAR
I think you only need to trap WM_CHAR though.
static int WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
/* Select Case uMsg */
switch(msg){
case WM_KEYDOWN:
//MsgBox("WM_KEYDOWN", "", 0);
return 0;
case WM_CHAR:
//MsgBox("WM_CHAR", "", 0);
return 0;
}
return CallWindowProc((WNDPROC)PrevProc, hwnd, msg, wParam, lParam);
}
Here is the listing that I used.
/****************************************************************************
* *
* File : main.c *
* *
* Purpose : Generic Win32 application. *
* *
* History : Date Reason *
* 00/00/00 Created *
* *
****************************************************************************/
#define WIN32_LEAN_AND_MEAN /* speed up compilations */
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <richedit.h>
#include "main.h"
/** Prototypes **************************************************************/
static LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM);
/** Global variables ********************************************************/
static HANDLE ghInstance;
HWND Edit1;
static WNDPROC PrevProc;
HANDLE hlib;
int MsgBox(char *Msg, char *Title, int Num)
{
return MessageBox(GetActiveWindow(), Msg, Title, Num);
}
static int WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
/* Select Case uMsg */
switch(msg){
case WM_KEYDOWN:
//MsgBox("WM_KEYDOWN", "", 0);
return 0;
case WM_CHAR:
//MsgBox("WM_CHAR", "", 0);
return 0;
}
return CallWindowProc((WNDPROC)PrevProc, hwnd, msg, wParam, lParam);
}
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
WNDCLASS wc;
HWND hwnd;
MSG msg;
ghInstance = hInstance;
hlib = LoadLibrary(_T("riched20.dll")); // Rich Edit v2.0, v3.0
/* Register the main window class */
wc.lpszClassName = _T("win1Class");
wc.lpfnWndProc = MainWndProc;
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.hInstance = ghInstance;
wc.hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDR_ICO_MAIN));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if (!RegisterClass(&wc))
return 1;
/* Create the main window */
hwnd = CreateWindow(_T("win1Class"), _T("win1 Program"), WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, ghInstance, NULL);
if (!hwnd)
return 1;
/* Show and paint the main window */
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
/* Pump messages until we are done */
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
static LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
Edit1 = CreateWindow(RICHEDIT_CLASS, NULL, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE | WS_BORDER | ES_LEFT | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 0, 0, 550, 450, hwnd, (HMENU)NULL, ghInstance, NULL);
PrevProc = (WNDPROC)SetWindowLong((HWND)Edit1, GWL_WNDPROC, (LONG)WindowProc);
break;
case WM_CLOSE:
SetWindowLong((HWND)Edit1, GWL_WNDPROC, (LONG)PrevProc);
CloseWindow(Edit1);
FreeLibrary(hlib);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return FALSE;
}
John
QuoteI think you only need to trap WM_CHAR though
make sense indeed!
thank you very very much, i'll check this !
You can also stop the 'carot' from appearing too, if that suits.
case WM_SETFOCUS:
return 0;
John
thank you very much.
after you pointed the wm_char i made a little test,
and found that i don't have to sub class.
i can have control in the wm_notify
i can trap the wm_char, and change the char or the msg,
so that the rtf won't get them.
#define CAST(x,y) ((x)(y))
LRESULT CALLBACK WndProc (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
MSGFILTER* ptrFltr;
/* Select Case Msg */
if(Msg==WM_NOTIFY)
{
ptrFltr=CAST(void*,lParam);
/* Select Case LOWORD(ptrFltr->nmhdr.code) */
if(LOWORD(ptrFltr->nmhdr.code)==EN_MSGFILTER)
{
/* Select Case LOWORD(ptrFltr->msg) */
if(LOWORD(ptrFltr->msg)==WM_CHAR)
{
MsgBox ("got wm_char on rtf","",0);
ptrFltr->wParam=0; // here i reset the char,
// instead, i can reset the msg: ptrFltr->msg = 0
return 0;
}
}
goto EndSelect_0;
}
if(Msg==WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
EndSelect_0:;
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
(this code won't compiled becuase it needs window creation+registeration)
If it solves your problem that's fine.
John