NO

Author Topic: question about keydown in RichText control  (Read 7407 times)

whatsup

  • Guest
question about keydown in RichText control
« on: September 16, 2010, 04:16:21 PM »
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 ?

JohnF

  • Guest
Re: question about keydown in RichText control
« Reply #1 on: September 16, 2010, 06:07:09 PM »
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
« Last Edit: September 16, 2010, 06:29:14 PM by JohnF »

whatsup

  • Guest
Re: question about keydown in RichText control
« Reply #2 on: September 16, 2010, 08:47:28 PM »
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
Code: [Select]
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;
}
« Last Edit: September 16, 2010, 09:37:12 PM by whatsup »

JohnF

  • Guest
Re: question about keydown in RichText control
« Reply #3 on: September 16, 2010, 09:56:53 PM »
I suggest that is not your code because it doesn't compile.

Anyway, this

Code: [Select]
PrevProc = (WNDPROC)SetWindowLong((HWND)Edit1, GWL_WNDPROC, (LONG) & WindowProc);

Will not work. What is "& WindowProc" meant to be?

John

whatsup

  • Guest
Re: question about keydown in RichText control
« Reply #4 on: September 16, 2010, 10:03:25 PM »
i posted only part of it.
about your question, this is the address of WindowProc function.
and it works very well.

JohnF

  • Guest
Re: question about keydown in RichText control
« Reply #5 on: September 17, 2010, 07:01:10 AM »
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.

Code: [Select]
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.

Code: [Select]
/****************************************************************************
 *                                                                          *
 * 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
« Last Edit: September 17, 2010, 11:07:45 AM by JohnF »

whatsup

  • Guest
Re: question about keydown in RichText control
« Reply #6 on: September 17, 2010, 12:14:23 PM »
Quote
I think you only need to trap WM_CHAR though
make sense indeed!

thank you very very much, i'll check this !

JohnF

  • Guest
Re: question about keydown in RichText control
« Reply #7 on: September 17, 2010, 01:07:14 PM »
You can also stop the 'carot' from appearing too, if that suits.

Code: [Select]
  case WM_SETFOCUS:
    return 0;

John

whatsup

  • Guest
Re: question about keydown in RichText control
« Reply #8 on: September 18, 2010, 10:10:09 PM »
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.

Code: [Select]
#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)
« Last Edit: September 18, 2010, 11:16:56 PM by whatsup »

JohnF

  • Guest
Re: question about keydown in RichText control
« Reply #9 on: September 18, 2010, 10:15:06 PM »
If it solves your problem that's fine.

John