Is there a possible way I can connect the WNDCLASSEX to the class in Gtk::WIndow??!
because I'm working on tray icon of gtkmm program for Windows. I already have a TrayIcon using this :

Shell_NotifyIcon(NIM_ADD, &g_notifyIconData);

But there is no function, it only display an icon it doesn't go in LRESULT Callback WndProc(.....).

NOTIFYICONDATA g_notifyIconData;
HWND g_hwnd;

Gtk::Window * mainWindow;
g_hwnd = reinterpret_cast<HWND>(GDK_WINDOW_HWND(mainWindow->get_window()->gobj())); //Gtk::window to HWND //everytime mainWindow run there's a tray icon, if the mainWindow quit it removes the tray icon

void MainWindow::InitNotifyIconData()
{

  memset( &g_notifyIconData, 0, sizeof( NOTIFYICONDATA ) ) ;

  g_notifyIconData.cbSize = sizeof(NOTIFYICONDATA);

  g_notifyIconData.hWnd = g_hwnd;
  g_notifyIconData.uID = ID_TRAY_APP_ICON;

  g_notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP ;

  g_notifyIconData.uCallbackMessage = WM_TRAYICON; 

  g_notifyIconData.hIcon = (HICON)LoadImage( NULL, TEXT("tray.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE  ) ;

  stringcopy(g_notifyIconData.szTip, TEXT("TrayIcon"));

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     // I need to connect here

  if ( message==WM_TASKBARCREATED && !IsWindowVisible( g_hwnd ) )
  {
    Minimize();
    return 0;
  }

  switch (message)
  {
  case WM_CREATE:

    g_menu = CreatePopupMenu();

    AppendMenu(g_menu, MF_STRING, ID_TRAY_EXIT_CONTEXT_MENU_ITEM,  TEXT( "Exit" ) );

    break;

  case WM_SYSCOMMAND:
    switch( wParam & 0xfff0 )  
    {
    case SC_MINIMIZE:
    case SC_CLOSE:  
      Minimize() ;
      return 0 ;
      break;
    }
    break;

 
  case WM_TRAYICON:
    {

      switch(wParam)
      {
      case ID_TRAY_APP_ICON:
        break;
      }

      if (lParam == WM_LBUTTONUP)
      {
        Restore();
      }
      else if (lParam == WM_RBUTTONDOWN) 
      {
      
        POINT curPoint ;
        GetCursorPos( &curPoint ) ;

        SetForegroundWindow(hwnd); 

        UINT clicked = TrackPopupMenu(

          g_menu,
          TPM_RETURNCMD | TPM_NONOTIFY, 
          curPoint.x,
          curPoint.y,
          0,
          hwnd,
          NULL

        );

        if (clicked == ID_TRAY_EXIT_CONTEXT_MENU_ITEM)
        {
          PostQuitMessage( 0 ) ;
        }
      }
    }
    break;

  case WM_NCHITTEST:
  {
    UINT uHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
    if(uHitTest == HTCLIENT)
      return HTCAPTION;
    else
      return uHitTest;
  }

  case WM_CLOSE:
    Minimize() ;
    return 0;
    break;

  case WM_DESTROY:
    PostQuitMessage (0);
    break;

  }

  return DefWindowProc( hwnd, message, wParam, lParam ) ;
}

WNDCLASSEX has lpfnWndProc = WndProc which is I think the one that connect to the LRESULT Callback WndProc(.....). But I can't declare my class in Gtk to WNDCLASSEX. Thanks in advance! :)

Dani AI

Generated

Short answer: you can’t “RegisterClassEx the Gtk::Window” so Windows will call your WndProc for it — GTK/GDK creates the native window class and manages it. Two workable options: create your own small native window (hidden or message-only) and give its HWND to Shell_NotifyIcon (recommended), or carefully subclass the Gtk window’s HWND with SetWindowLongPtr (possible but fragile). already found the HWND via GDK, but that alone doesn’t register your WndProc; and ’s change of message id won’t help if no Win32 window procedure is actually receiving the callback. Shell_NotifyIcon docs and GDK’s Win32 helpers explain the HWND relationship.

A robust approach is to register a tiny Win32 class and create a hidden/message-only window to own the tray icon and receive the uCallbackMessage. Pass that HWND in your NOTIFYICONDATA and handle the callback/menus in that WndProc. Use the TaskbarCreated registered message to re-add icons after explorer restarts. Message-only/hidden windows keep your Windows plumbing separate from GTK and avoid many lifecycle problems. See the Windows message-only window and taskbar docs for details.

If you prefer to subclass the Gtk window instance, get the HWND via the GDK Win32 helper (GDK_SURFACE_HWND / GDK_WINDOW_HWND) and replace that window’s WNDPROC with SetWindowLongPtr, saving the original and forwarding unhandled messages with CallWindowProc. That works, but GDK may create or replace native windows (gdk_window_ensure_native), so subclassing can break across GTK versions or on widget reparenting — use it only if you control lifetime carefully.

When a tray message needs to touch GTK widgets, marshal back to the GTK main loop (g_idle_add or Glib::Dispatcher) so GUI calls run on the GUI thread. Also remember to remove the icon on exit and set NOTIFYICONDATA.cbSize/uVersion correctly for the shell behavior you expect. Example subclass call (minimal):

WNDPROC old = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)MyWndProc);

References: Windows Shell_NotifyIcon, message-only windows, SetWindowLongPtr, GDK Win32 helpers, and gtkmm/GLib marshalling docs.

Recommended Answers

All 2 Replies

Instead of the WM_TRAYICON message, try WM_USER_SHELLICON.

Instead of the WM_TRAYICON message, try WM_USER_SHELLICON.

Its still the same. :( Hmm.. How about this, is it possible way to register a class in gtkmm (Gtk::Window * MainWindow) in RegisterClassEx()? Because I need to have WndProc and I can't register the MainWindow in RegisterClassEx.

WNDCLASSEX wc;
wc.lpfnWndProc   = WndProc;
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.