mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
220 lines
4.3 KiB
C++
220 lines
4.3 KiB
C++
#include "CtrlLib.h"
|
|
|
|
#ifdef GUI_WIN
|
|
#ifndef PLATFORM_WINCE
|
|
|
|
#include <commdlg.h>
|
|
#include <cderr.h>
|
|
#include <shellapi.h>
|
|
|
|
#endif
|
|
#endif
|
|
|
|
namespace Upp {
|
|
|
|
|
|
#ifdef GUI_WIN
|
|
|
|
#ifndef PLATFORM_WINCE
|
|
#define LLOG(x)
|
|
|
|
enum {
|
|
UM_TASKBAR_ = WM_USER + 1024,
|
|
NIN_BALLOONSHOW_ = WM_USER + 2,
|
|
NIN_BALLOONHIDE_ = WM_USER + 3,
|
|
NIN_BALLOONTIMEOUT_ = WM_USER + 4,
|
|
NIN_BALLOONUSERCLICK_ = WM_USER + 5,
|
|
};
|
|
|
|
TrayIcon::TrayIcon()
|
|
{
|
|
Create(NULL, WS_POPUP, 0, false, 0, 0);
|
|
Ctrl::Hide();
|
|
Zero(nid);
|
|
nid.sz = IsWin2K() ? sizeof(NotifyIconNew) : sizeof(NotifyIconOld);
|
|
nid.message = UM_TASKBAR_;
|
|
nid.hwnd = GetHWND();
|
|
static int id;
|
|
nid.id = ++id;
|
|
visible = false;
|
|
Show();
|
|
}
|
|
|
|
TrayIcon::~TrayIcon()
|
|
{
|
|
Hide();
|
|
if(nid.icon)
|
|
DestroyIcon(nid.icon);
|
|
}
|
|
|
|
void TrayIcon::Notify(dword msg)
|
|
{
|
|
if(visible) {
|
|
nid.flags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
|
|
if(nid.icon)
|
|
DestroyIcon(nid.icon);
|
|
nid.icon = SystemDraw::IconWin32(icon);
|
|
String stip = ToSystemCharset(tip);
|
|
int len = min(stip.GetLength(), 125);
|
|
memcpy(nid.tip, stip, len);
|
|
nid.tip[len] = 0;
|
|
BOOL Status = Shell_NotifyIcon(msg, (NOTIFYICONDATA *)&nid);
|
|
// To prevent from Shell_NotifyIcon bugs...
|
|
// discussed here : http://msdn.microsoft.com/en-us/library/bb762159(v=vs.85).aspx
|
|
// and here : http://issuetracker.delphi-jedi.org/bug_view_advanced_page.php?bug_id=3747
|
|
if (Status == FALSE) {
|
|
// The status of Shell_NotifyIcon is FALSE, in the case of NIM_ADD/NIM_MODIFY, we will try to Modify
|
|
// If the modify is OK then we cas consider that the add was worked.
|
|
// Same, case with delete, we can try modify and if KO then we can consider that is icon
|
|
// was deleted correctly. In other cases, we will retry after 50ms
|
|
DWORD ErrorCode = GetLastError();
|
|
if(ErrorCode == ERROR_SUCCESS || ErrorCode == ERROR_TIMEOUT) {
|
|
for(int retry = 0; retry < 60; retry++) {
|
|
Sleep(50);
|
|
if(Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA *)&nid) == (msg != NIM_DELETE))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TrayIcon::Message(int type, const char *title, const char *text, int timeout)
|
|
{
|
|
if(!IsWin2K())
|
|
return;
|
|
nid.flags = 0x10;
|
|
*nid.info = *nid.title = 0;
|
|
if(text) {
|
|
String h = ToSystemCharset(text);
|
|
memcpy(nid.info, h, min(h.GetLength(), 255) + 1);
|
|
nid.info[255] = 0;
|
|
}
|
|
if(title) {
|
|
String h = ToSystemCharset(title);
|
|
memcpy(nid.title, h, min(h.GetLength(), 63) + 1);
|
|
nid.title[63] = 0;
|
|
}
|
|
nid.infoflags = type;
|
|
nid.timeout = minmax(timeout, 10, 30) * 1000;
|
|
Shell_NotifyIcon(NIM_MODIFY, (NOTIFYICONDATA *)&nid);
|
|
}
|
|
|
|
void TrayIcon::Show(bool b)
|
|
{
|
|
if(b == visible)
|
|
return;
|
|
if(visible)
|
|
Notify(NIM_DELETE);
|
|
visible = b;
|
|
if(visible)
|
|
Notify(NIM_ADD);
|
|
}
|
|
|
|
TrayIcon& TrayIcon::Icon(const Image &img)
|
|
{
|
|
icon = img;
|
|
Notify(NIM_MODIFY);
|
|
return *this;
|
|
}
|
|
|
|
TrayIcon& TrayIcon::Tip(const char *text)
|
|
{
|
|
tip = text;
|
|
Notify(NIM_MODIFY);
|
|
return *this;
|
|
}
|
|
|
|
void TrayIcon::Menu(Bar& bar)
|
|
{
|
|
WhenBar(bar);
|
|
}
|
|
|
|
void TrayIcon::LeftDown()
|
|
{
|
|
WhenLeftDown();
|
|
}
|
|
|
|
void TrayIcon::LeftUp()
|
|
{
|
|
WhenLeftUp();
|
|
}
|
|
|
|
void TrayIcon::LeftDouble()
|
|
{
|
|
WhenLeftDouble();
|
|
}
|
|
|
|
void TrayIcon::DoMenu(Bar& bar)
|
|
{
|
|
Menu(bar);
|
|
}
|
|
|
|
void TrayIcon::BalloonLeftDown()
|
|
{
|
|
WhenBalloonLeftDown();
|
|
}
|
|
|
|
void TrayIcon::BalloonShow()
|
|
{
|
|
WhenBalloonShow();
|
|
}
|
|
|
|
void TrayIcon::BalloonHide()
|
|
{
|
|
WhenBalloonHide();
|
|
}
|
|
|
|
void TrayIcon::BalloonTimeout()
|
|
{
|
|
WhenBalloonTimeout();
|
|
}
|
|
|
|
LRESULT TrayIcon::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if(message == WM_QUERYENDSESSION) {
|
|
Shutdown();
|
|
return true;
|
|
}
|
|
if(message == UM_TASKBAR_)
|
|
switch(lParam) {
|
|
case WM_LBUTTONDOWN:
|
|
LeftDown();
|
|
return TRUE;
|
|
case WM_LBUTTONUP:
|
|
LeftUp();
|
|
return TRUE;
|
|
case WM_LBUTTONDBLCLK:
|
|
::SetForegroundWindow(nid.hwnd);
|
|
LeftDouble();
|
|
return TRUE;
|
|
case WM_RBUTTONDOWN:
|
|
::SetForegroundWindow(nid.hwnd);
|
|
MenuBar::Execute(NULL, THISBACK(DoMenu), GetMousePos());
|
|
return TRUE;
|
|
case NIN_BALLOONSHOW_:
|
|
BalloonShow();
|
|
return TRUE;
|
|
case NIN_BALLOONHIDE_:
|
|
BalloonHide();
|
|
return TRUE;
|
|
case NIN_BALLOONTIMEOUT_:
|
|
BalloonTimeout();
|
|
return TRUE;
|
|
case NIN_BALLOONUSERCLICK_:
|
|
BalloonLeftDown();
|
|
return TRUE;
|
|
}
|
|
static UINT WM_TASKBARCREATED = RegisterWindowMessageA("TaskbarCreated");
|
|
if(message == WM_TASKBARCREATED) {
|
|
LLOG("TrayIcon::WM_TASKBARCREATED");
|
|
visible = false;
|
|
Show();
|
|
}
|
|
return Ctrl::WindowProc(message, wParam, lParam);
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
|
|
}
|