views:

71

answers:

3

Hi,

I'm implementing a custom combobox to behave like a searchbox. It is constructed from an Edit control, a Button and a Listbox.

I'm trying to open the listbox on mouse click on the button, it seemed to be simple but become complicated. First I tried to manage the mouse click on the "BN_CLICKED", but then I discovered it's too late and I'd like to open the listbox already on "WM_LBUTTONDOWN" (and on "WM_LBUTTONDBLCLK"), the problem is, when I'm trying to open the list box on this message the listbox receives "WM_KILLFOCUS" and being closed right after being opened for a moment, and later the button receives the "WM_SETFOCUS" message, I was thinking to open the list box in the "WM_SETFOCUS" which receives the button, but I can't rely on this message because it won't be sent each button click (for example when I keep clicking the button).

Thanks ahead!
mike.

+1  A: 

Wouldn't it be easier to just start with a combobox and derive a window class from that?

WNDPROC comboboxwndproc;

LRESULT CALLBACK MyComboBoxWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  switch (uMsg) {
    /* do your thing */
  }

  return CallWindowProc(comboboxwndproc, hwnd, uMsg, wParam, lParam);
}

void register_custom_combobox() {
  WINDOWCLASSEX mycbwc;
  char mycbwcname[] = "MYCOMBOBOX";
  mycbwc.cbSize = sizeof(WNDCLASSEX);
  GetClassInfoEx(NULL, "COMBOBOX", &mycbwc);
  comboboxwndproc = cbwc.lpfnWndProc;
  mycbwc.lpfnWndProc = MyComboBoxWndProc;
  mycbwc.hInst = my_instance;
  mycbwc.lpszClassName = mycbwcname;
  RegisterClassEx(&mycbwc);
}

If you wanted to, you could, instead of using the global variable, reserve space in the Class Extra area. Then in the custom window proc, check to see if it has been set already or not, and if not, request the combobox class info again and put the pointer to the combobox window proc in the Class Extra area.

wich
A: 

Alternatively, you could override the window proc on creation instead of registering a new window class:

WNDPROC g_ComboBoxProc;

LRESULT CALLBACK SearchBoxProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  // Special handling here.

  return CallWindowProc(g_ComboBoxProc, hwnd, uMsg, wParam, lParam);
}

HWND CreateSearchBox(LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, 
                     int w, int h, HWND hWndParent, HMENU hMenu, 
                     HINSTANCE hInstance, LPVOID lpParam) {
  HWND hwnd = CreateWindow(TEXT("COMBOBOX"), lpWindowName, dwStyle, 
                           x, y, w, h, hWndParent, hMenu, hInstance);
  if (hwnd) {
    g_ComboBoxProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, 
                                              (WNDPROC) SearchBoxProc);
  }

  return hwnd;
}

Though SetWindowSubclass should probably be used instead.

Alex
A: 

Well, I yet prefer to do it the way I've described (i.e. edit+button+listbox). Any idea how to handle the messages so that on button mouse click the listbox will be opened?

thanks!

mike
I think this will be very difficult as you need to manage the focus and defocus of the three indiviual window items, which will be very difficult to do correctly.
wich