12-24-2025, 09:54 PM
This program hides the program icon in the Windows tray on the right (to system items) and also allows you to call it.
Program use Tray.H file
Tray.H:
Tray.bas:
Program use Tray.H file
Tray.H:
Code: (Select All)
#ifndef QB64_TRAY_H
#define QB64_TRAY_H
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include <stdint.h>
#include <string.h>
/* --- runtime link na Shell_NotifyIconA (žádné linkování navíc) --- */
static HMODULE qb64_tray_shell32 = NULL;
typedef BOOL (WINAPI *qb64_Shell_NotifyIconA_t)(DWORD, PNOTIFYICONDATAA);
static qb64_Shell_NotifyIconA_t qb64_Shell_NotifyIconA_p = NULL;
static NOTIFYICONDATAA qb64_tray_nid;
static int qb64_tray_icon_added = 0;
static HWND qb64_tray_hwnd = NULL;
static WNDPROC qb64_tray_oldproc = NULL;
static UINT qb64_tray_cbmsg = (WM_APP + 0x4B64); /* libovolné "unikátní" číslo */
static void qb64_tray_load_shell_notifyicon(void) {
if (qb64_Shell_NotifyIconA_p) return;
qb64_tray_shell32 = LoadLibraryA("shell32.dll");
if (!qb64_tray_shell32) return;
qb64_Shell_NotifyIconA_p = (qb64_Shell_NotifyIconA_t)GetProcAddress(qb64_tray_shell32, "Shell_NotifyIconA");
}
static HICON qb64_tray_get_window_icon(HWND hwnd) {
HICON h = (HICON)SendMessageA(hwnd, WM_GETICON, ICON_SMALL, 0);
if (!h) h = (HICON)(uintptr_t)GetClassLongPtrA(hwnd, GCLP_HICONSM);
if (!h) h = (HICON)SendMessageA(hwnd, WM_GETICON, ICON_BIG, 0);
if (!h) h = (HICON)(uintptr_t)GetClassLongPtrA(hwnd, GCLP_HICON);
if (!h) h = LoadIconA(NULL, IDI_APPLICATION);
return h;
}
static void qb64_tray_fill_nid(const char* tip) {
ZeroMemory(&qb64_tray_nid, sizeof(qb64_tray_nid));
qb64_tray_nid.cbSize = sizeof(qb64_tray_nid); /* doporučený postup */
qb64_tray_nid.hWnd = qb64_tray_hwnd;
qb64_tray_nid.uID = 1;
qb64_tray_nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
qb64_tray_nid.uCallbackMessage = qb64_tray_cbmsg;
qb64_tray_nid.hIcon = qb64_tray_get_window_icon(qb64_tray_hwnd);
if (tip && tip[0]) {
strncpy(qb64_tray_nid.szTip, tip, sizeof(qb64_tray_nid.szTip) - 1);
qb64_tray_nid.szTip[sizeof(qb64_tray_nid.szTip) - 1] = '\0';
} else {
qb64_tray_nid.szTip[0] = '\0';
}
}
static void qb64_tray_add_icon(void) {
qb64_tray_load_shell_notifyicon();
if (!qb64_Shell_NotifyIconA_p || !qb64_tray_hwnd) return;
if (!qb64_tray_icon_added) {
qb64_Shell_NotifyIconA_p(NIM_ADD, &qb64_tray_nid);
qb64_tray_icon_added = 1;
} else {
qb64_Shell_NotifyIconA_p(NIM_MODIFY, &qb64_tray_nid);
}
}
static void qb64_tray_delete_icon(void) {
qb64_tray_load_shell_notifyicon();
if (!qb64_Shell_NotifyIconA_p || !qb64_tray_hwnd) return;
if (qb64_tray_icon_added) {
qb64_Shell_NotifyIconA_p(NIM_DELETE, &qb64_tray_nid);
qb64_tray_icon_added = 0;
}
}
static void qb64_tray_restore_window(void) {
if (!qb64_tray_hwnd) return;
qb64_tray_delete_icon();
ShowWindow(qb64_tray_hwnd, SW_RESTORE);
SetForegroundWindow(qb64_tray_hwnd);
}
static void qb64_tray_hide_window(void) {
if (!qb64_tray_hwnd) return;
qb64_tray_add_icon();
ShowWindow(qb64_tray_hwnd, SW_HIDE);
}
static LRESULT CALLBACK qb64_tray_wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_SYSCOMMAND) {
UINT cmd = (UINT)(wParam & 0xFFF0);
if (cmd == SC_MINIMIZE) {
qb64_tray_hide_window();
return 0;
}
}
if (msg == qb64_tray_cbmsg) {
if (lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONUP) {
qb64_tray_restore_window();
return 0;
}
}
if (msg == WM_DESTROY) {
qb64_tray_delete_icon();
}
return CallWindowProcA(qb64_tray_oldproc, hwnd, msg, wParam, lParam);
}
/* --- API pro QB64PE --- */
extern "C" int Tray_Enable(uintptr_t hwnd, const char* tip) {
if (!hwnd) return 0;
qb64_tray_hwnd = (HWND)hwnd;
if (!qb64_tray_oldproc) {
qb64_tray_oldproc = (WNDPROC)(uintptr_t)GetWindowLongPtrA(qb64_tray_hwnd, GWLP_WNDPROC);
SetLastError(0);
LONG_PTR prev = SetWindowLongPtrA(qb64_tray_hwnd, GWLP_WNDPROC, (LONG_PTR)qb64_tray_wndproc);
if (prev == 0 && GetLastError() != 0) {
qb64_tray_oldproc = NULL;
return 0;
}
}
qb64_tray_fill_nid(tip);
return 1;
}
extern "C" void Tray_Disable(void) {
if (!qb64_tray_hwnd) return;
qb64_tray_delete_icon();
if (qb64_tray_oldproc) {
SetWindowLongPtrA(qb64_tray_hwnd, GWLP_WNDPROC, (LONG_PTR)qb64_tray_oldproc);
qb64_tray_oldproc = NULL;
}
}
extern "C" void Tray_Hide(void) { qb64_tray_hide_window(); }
extern "C" void Tray_Show(void) { qb64_tray_restore_window(); }
extern "C" void Tray_SetTip(const char* tip) {
qb64_tray_fill_nid(tip);
if (qb64_tray_icon_added) qb64_tray_add_icon(); /* MOD */
}
#else
/* Non-Windows: prázdné stuby */
extern "C" int Tray_Enable(unsigned long long, const char*) { return 0; }
extern "C" void Tray_Disable(void) {}
extern "C" void Tray_Hide(void) {}
extern "C" void Tray_Show(void) {}
extern "C" void Tray_SetTip(const char*) {}
#endif
#endifTray.bas:
Code: (Select All)
Option _Explicit
Declare Library "tray"
Function Tray_Enable% (ByVal hwnd As _Offset, tip As String)
Sub Tray_Disable
Sub Tray_Hide
Sub Tray_Show
Sub Tray_SetTip (tip As String)
End Declare
_Title "QB64PE Tray Demo"
Screen _NewImage(640, 240, 32)
Dim ok%
ok% = Tray_Enable(_WindowHandle, "My Apllication" + Chr$(0))
If ok% = 0 Then Print "Tray_Enable fail."
Print "H = Hide to tray, S = show, ESC = end"
Dim k$
Do
k$ = UCase$(InKey$)
If k$ = "H" Then Tray_Hide
If k$ = "S" Then Tray_Show
If k$ = Chr$(27) Then Exit Do
_Limit 60
Loop
Tray_Disable
System

