AckiB
Mitglied
hallo, ich habe mal wieder ein Problem 
ich habe folgenden Code, um ein Programm als Icon in der "tray bar" anzuzeigen:
tray.h
tray.cpp
die Resource-Datei(en) spare ich mir hier, da wird nur das Icon definiert... 
ok, das läuft wunderbar...
was aber, wenn ich kein Windows-Fenster habe?
z.B. wenn ich ein FLTK-Fenster oder sogar nur eine DOS-Anwendung habe?
ich kann das Icon dann zwar im Tray anzeigen, aber ich habe dann ja keine Callback-Funktion und kann somit nicht feststellen ob und was/wie das Tray-Icon angeklickt wurde !?
bei einem FLTK-Fenster mache ich das jetzt so, dass ich ein Windows-Fenster erstelle (wie oben) und dieses dann verstecke, indem ich es als child des FLTK-Fensters definiere und außerhalb des FLTK-Fensters platziere...
das finde ich aber mehr als unelegant!
hat da jemand eine Idee zu?
danke, Acki

ich habe folgenden Code, um ein Programm als Icon in der "tray bar" anzuzeigen:
tray.h
Code:
#ifndef _TRAY_H_
#define _TRAY_H_
#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include "resources.rch"
#ifndef RC_INVOKED //variable definitions and function prototypes just confuse the resource compiler
void minimize(HWND hwnd);
void restore(HWND hwnd);
bool minimized = false;
const int TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
#endif // 8: #ifndef RC_INVOKED
#define IDI_ICON 0
#define IDC_MINIMIZE 1
#define IDI_TRAYICON 2
#define IDM_TRAYEXIT 3
#define IDM_TRAYHELP 4
#define IDM_TRAYABOUT 5
#define MSG_MINTRAYICON (WM_USER+0)
#endif // 1: #ifndef _TRAY_H_
tray.cpp
Code:
#include "tray.h"
#include <stdio.h>
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
char szClassName[ ] = "TrayMinimizerClass__";
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil){
HWND hwnd;
MSG messages;
WNDCLASSEX wincl;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return 0;
hwnd = CreateWindowEx (
0,
szClassName,
"Minimize to Tray Example",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
544,
375,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);
ShowWindow (hwnd, nFunsterStil);
while (GetMessage (&messages, NULL, 0, 0)){
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
if ( (message == TASKBARCREATED) && (minimized) ){
minimize(hwnd);
return 0;
}
switch (message){
case WM_CREATE:
CreateWindowEx(0, "BUTTON", "Click to minimize to tray", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT | BS_CENTER | BS_VCENTER, 200, 50, 300, 25, hwnd, (HMENU)IDC_MINIMIZE, GetModuleHandle(NULL), NULL);
break;
case WM_COMMAND:
if ( (HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == IDC_MINIMIZE) ){
if (minimized) restore(hwnd);
else minimize(hwnd);
}
break;
case MSG_MINTRAYICON:{
if (wParam != IDI_TRAYICON) break;
if (lParam == WM_LBUTTONUP){
restore(hwnd);
}
else if (lParam == WM_RBUTTONUP){
HMENU myMenu = NULL;
myMenu = CreatePopupMenu();
AppendMenu(myMenu, MF_STRING, IDM_TRAYEXIT, "Exit");
AppendMenu(myMenu, MF_STRING, IDM_TRAYHELP, "Help");
AppendMenu(myMenu, MF_STRING, IDM_TRAYABOUT, "About");
DWORD mp = GetMessagePos(); //get the position of the mouse at the time the icon was clicked (or, at least, the time this message was generated).
SetForegroundWindow(hwnd); //even though the window is hidden, we must set it to the foreground window because of popup-menu peculiarities. See the Remarks section of the MSDN page for TrackPopupMenu.
UINT clicked = TrackPopupMenu(myMenu, TPM_RETURNCMD | TPM_NONOTIFY /*don't send me WM_COMMAND messages about this window, instead return the identifier of the clicked menu item*/, GET_X_LPARAM(mp), GET_Y_LPARAM(mp), 0, hwnd, NULL); //display the menu. you MUST #include <windowsx.h> to use those two macros.
SendMessage(hwnd, WM_NULL, 0, 0); //send benign message to window to make sure the menu goes away.
if (clicked == IDM_TRAYEXIT) SendMessage(hwnd, WM_DESTROY, 0, 0);
else if (clicked == IDM_TRAYHELP) MessageBox(hwnd, "Click the button to minimize to the system tray.", "Tray Example Help", MB_OK | MB_ICONINFORMATION);
else if (clicked == IDM_TRAYABOUT) MessageBox(hwnd, "Tray Example: Demonstrates minimizing a window to the tray.", "About Tray Example", MB_OK | MB_ICONINFORMATION);
}
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
void minimize(HWND hwnd){
NOTIFYICONDATA nid = { 0 };
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uID = IDI_TRAYICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = MSG_MINTRAYICON;
nid.hIcon = (HICON)LoadImage(
GetModuleHandle(NULL),
MAKEINTRESOURCE(prgIcon),
IMAGE_ICON,
16, 16,
0);
strcpy(nid.szTip, "My very own system tray icon!");
Shell_NotifyIcon(NIM_ADD, &nid);
ShowWindow(hwnd, SW_HIDE);
minimized = true;
}
void restore(HWND hwnd){
NOTIFYICONDATA nid = { 0 };
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uID = IDI_TRAYICON;
Shell_NotifyIcon(NIM_DELETE, &nid);
ShowWindow(hwnd, SW_SHOW);
minimized = false;
}

ok, das läuft wunderbar...
was aber, wenn ich kein Windows-Fenster habe?
z.B. wenn ich ein FLTK-Fenster oder sogar nur eine DOS-Anwendung habe?

ich kann das Icon dann zwar im Tray anzeigen, aber ich habe dann ja keine Callback-Funktion und kann somit nicht feststellen ob und was/wie das Tray-Icon angeklickt wurde !?

bei einem FLTK-Fenster mache ich das jetzt so, dass ich ein Windows-Fenster erstelle (wie oben) und dieses dann verstecke, indem ich es als child des FLTK-Fensters definiere und außerhalb des FLTK-Fensters platziere...
das finde ich aber mehr als unelegant!

hat da jemand eine Idee zu?
danke, Acki
Zuletzt bearbeitet: