Click here to Skip to main content
11,925,292 members (59,438 online)
Click here to Skip to main content
Add your own
alternative version


13 bookmarked

Extended Outlook Textbox to prevent text erase on lost focus

, 17 Aug 2005
Rate this:
Please Sign up or sign in to vote.
This article is provided to change the default behaviour of the Outlook textbox. The lost Win32 focus message is handled to save the text before the textbox looses focus.


Some time ago I had to implement a toolbar in Outlook that contained a textbox with a 'Go' button that started a search. After creating the textbox and the button I noticed that the textbox was losing the text when it changed the focus. That was unacceptable in a search. So, I found this solution to that issue. It's a bit complex but I couldn't find another solution. It can be extended to handle the key press to get the Enter or any other key press. This article was written together with Gabriel Benmergui.

Using the code

You can use this code by copying the hook.cpp / h and OutlookEdit.cpp / h in your project and instantiating COutlookEdit objects in your toolbar. This project creates an Outlook addin that creates a toolbar with two textboxes inside.

Points of interest

Outlook implements the TextBox control with a RichEdit20W (in Office 97 a EDIT is created) Win32 control inside. The problem is that RichEdit20W is not created when the textbox is created so it's necessary to create a window creation hook to know when it is created. To do this I've installed a WH_CBT hook to handle the creation of the RichEdit20W. When it is created we have to post a message to the COutlookEditMgr window created for this purpose.

                        WPARAM wParam, LPARAM lParam)
  if(nCode == HCBT_CREATEWND) {
    TCHAR *className = (TCHAR *) cs->lpszClass;
    HWND hWnd = (HWND) wParam;
    TCHAR aux[1024];

    if(!HIWORD(cs->lpszClass)) {
      if(GetClassName(hWnd, aux, 
                 sizeof(aux)/sizeof(TCHAR)-1) == 0) {
        className = NULL;
      else {
        className = aux;

    if(className) {
      // textbox is represented by a RichEdit20W in 
      // 2K and upper and it is created
      // in a mouse over or when it gets focus
      if(!_tcscmp(className, _T("RichEdit20W"))) {
        HRESULT hr = CallNextHookEx(HookHandle, 
                               nCode, wParam, lParam);

        // post the message to the edit manager window
                          (WPARAM) hWnd, 0);
        return hr;

  // Call the next handler in the chain
  return CallNextHookEx(HookHandle, nCode, 
                              wParam, lParam);

When the RichEdit20W is created we have to detect if the new window is owned by any of our COutlookEdit controls and subclass the RichEdit20W if affirmative. Here all the COutlookEdit controls are checked and if any one matches the window proc is changed.

void COutlookEditMgr::OnNewRichEdit20W(HWND hWnd)
  COutlookEdit *edit;

  // Once the RichEdit is called, check if it 
  // belongs to one of the edit controls
  for(COutlookEditList::iterator it=_editList.begin(); 
                             it!=_editList.end(); ++it) {
    edit = *it;

    // Check if the window handle belongs to 
    // any of the controls, and hook it
    if(edit->VerifyWindow(hWnd)) {

BOOL COutlookEdit::VerifyWindow(HWND hwnd)
  if(_hCtrlWnd != NULL) {
    return FALSE;

  // Get the handle's rectangle, and check 
  // if the control is inside it
  POINT p;
  RECT rect;

  GetWindowRect(hwnd, &rect);

  p.x = m_pEdit->GetLeft() + 
                m_pEdit->GetWidth() / 2;
  p.y = m_pEdit->GetTop() + 
                m_pEdit->GetHeight() / 2;

  return (p.x < rect.right && 
              p.x > rect.left &&
              p.y < rect.bottom && 
              p.y >;

void COutlookEdit::HookWindow(HWND hWnd)
  _hCtrlWnd = hWnd;
  _oldWndProc = (WNDPROC) GetWindowLong(hWnd, 
  SetWindowLong(hWnd, GWL_WNDPROC, 
                         (LONG) TextboxWndProc);

Now, we're almost done. Here is the new RichEdit20W window proc where you have to handle the Win32 control messages:

                              WPARAM wParam, LPARAM lParam)
  COutlookEdit *edit = 
  WNDPROC lpOldProc;

  if(edit == NULL) {
    OutputDebugStr("TextboxWndProc: edit == NULL.\n");
    return 0;

  lpOldProc = edit->GetOldWndProc();

    // if we don't handle this event the text 
    // is lost when the control lose focus
    // without pressing enter or tab
    case WM_KILLFOCUS:
      int length = SendMessage(hWnd, 
                          WM_GETTEXTLENGTH, 0, 0);
      TCHAR *buf = new TCHAR[length+1];

      SendMessage(hWnd, WM_GETTEXT, length+1, 
                                    (LPARAM) buf);

      delete [] buf;

  return CallWindowProc(lpOldProc, hWnd, 
                             msg, wParam, lParam);


  • 2nd Aug, 2005 - Article released.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Pablo Yabo
Technical Lead
Argentina Argentina
Pablo Yabo is a Software Developer since he was young, specialized in system internals.
In 2003 years ago founded with Sebastian Wain a Company named Nektra specialized in Outlook Express and Outlook Plugin Development.
Now there is a new Windows Live Mail API 2011 / 2009 that works on all the platforms Windows 7, Vista and XP

You may also be interested in...

Comments and Discussions

GeneralOffice 97 Pin
jprandi23-Mar-06 6:28
memberjprandi23-Mar-06 6:28 
GeneralRe: Office 97 Pin
Pablo Yabo23-Mar-06 6:31
memberPablo Yabo23-Mar-06 6:31 
QuestionVB.NET / C# ?? Pin
RobSA16-Feb-06 23:24
memberRobSA16-Feb-06 23:24 
AnswerRe: VB.NET / C# ?? Pin
Pablo Yabo17-Feb-06 2:52
memberPablo Yabo17-Feb-06 2:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.151126.1 | Last Updated 17 Aug 2005
Article Copyright 2005 by Pablo Yabo
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid