i2pd/Win32/Win32App.cpp

236 lines
8.0 KiB
C++
Raw Normal View History

2016-03-07 19:54:57 +00:00
#include <string.h>
2016-03-07 20:57:32 +00:00
#include <windows.h>
#include <shellapi.h>
#include "../Config.h"
2016-03-24 15:05:47 +00:00
#include "../version.h"
2016-03-08 16:24:29 +00:00
#include "resource.h"
2016-03-07 19:54:57 +00:00
#include "Win32App.h"
2016-03-14 20:12:56 +00:00
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
2016-03-07 19:54:57 +00:00
2016-03-07 20:57:32 +00:00
#define ID_ABOUT 2000
#define ID_EXIT 2001
#define ID_CONSOLE 2002
#define ID_APP 2003
2016-03-07 20:57:32 +00:00
2016-03-08 16:24:29 +00:00
#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)
2016-03-09 19:41:14 +00:00
namespace i2p
2016-03-07 20:57:32 +00:00
{
2016-03-09 19:41:14 +00:00
namespace win32
{
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
2016-03-07 20:57:32 +00:00
{
2016-03-09 19:41:14 +00:00
HMENU hPopup = CreatePopupMenu();
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
2016-03-09 19:41:14 +00:00
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
2016-03-07 20:57:32 +00:00
2016-03-09 19:41:14 +00:00
POINT p;
if (!curpos)
{
GetCursorPos (&p);
curpos = &p;
}
2016-03-07 20:57:32 +00:00
2016-03-09 19:41:14 +00:00
WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL);
SendMessage (hWnd, WM_COMMAND, cmd, 0);
2016-03-07 20:57:32 +00:00
2016-03-09 19:41:14 +00:00
DestroyMenu(hPopup);
}
2016-03-07 20:57:32 +00:00
2016-03-09 19:41:14 +00:00
static void AddTrayIcon (HWND hWnd)
{
NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.hWnd = hWnd;
nid.uID = ID_TRAY_ICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
2016-03-09 19:41:14 +00:00
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
2016-03-09 19:41:14 +00:00
strcpy (nid.szTip, "i2pd");
strcpy (nid.szInfo, "i2pd is running");
2016-03-09 19:41:14 +00:00
Shell_NotifyIcon(NIM_ADD, &nid );
}
2016-03-07 19:54:57 +00:00
2016-03-09 19:41:14 +00:00
static void RemoveTrayIcon (HWND hWnd)
2016-03-07 19:54:57 +00:00
{
2016-03-09 19:41:14 +00:00
NOTIFYICONDATA nid;
nid.hWnd = hWnd;
nid.uID = ID_TRAY_ICON;
Shell_NotifyIcon (NIM_DELETE, &nid);
}
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
2016-03-07 20:57:32 +00:00
{
2016-03-09 19:41:14 +00:00
case WM_CREATE:
2016-03-07 20:57:32 +00:00
{
2016-03-09 19:41:14 +00:00
AddTrayIcon (hWnd);
break;
}
case WM_CLOSE:
{
RemoveTrayIcon (hWnd);
PostQuitMessage (0);
break;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
2016-03-07 20:57:32 +00:00
{
2016-03-09 19:41:14 +00:00
case ID_ABOUT:
{
2016-03-24 15:05:47 +00:00
std::stringstream text;
text << "Version: " << I2PD_VERSION << " " << CODENAME;
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
2016-03-09 19:41:14 +00:00
return 0;
}
case ID_EXIT:
{
PostMessage (hWnd, WM_CLOSE, 0, 0);
return 0;
}
case ID_CONSOLE:
{
char buf[30];
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
2016-03-14 20:12:56 +00:00
snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
return 0;
}
case ID_APP:
{
ShowWindow(hWnd, SW_SHOW);
return 0;
}
2016-03-07 20:57:32 +00:00
}
2016-03-09 19:41:14 +00:00
break;
2016-03-07 20:57:32 +00:00
}
case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_MINIMIZE:
{
ShowWindow(hWnd, SW_HIDE);
return 0;
}
case SC_CLOSE:
{
std::string close; i2p::config::GetOption("close", close);
if (0 == close.compare("ask"))
switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?"
" You can add 'close' configuration option. Valid values are: ask, minimize, exit.",
"Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1))
{
case IDYES: close = "minimize"; break;
case IDNO: close = "exit"; break;
default: return 0;
}
if (0 == close.compare("minimize"))
{
ShowWindow(hWnd, SW_HIDE);
return 0;
}
if (0 != close.compare("exit"))
{
::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING);
return 0;
}
}
}
}
2016-03-09 19:41:14 +00:00
case WM_TRAYICON:
2016-03-07 20:57:32 +00:00
{
2016-03-09 19:41:14 +00:00
switch (lParam)
2016-03-07 20:57:32 +00:00
{
case WM_LBUTTONUP:
2016-03-09 19:41:14 +00:00
case WM_RBUTTONUP:
{
SetForegroundWindow (hWnd);
ShowPopupMenu(hWnd, NULL, -1);
PostMessage (hWnd, WM_APP + 1, 0, 0);
break;
}
2016-03-07 20:57:32 +00:00
}
2016-03-09 19:41:14 +00:00
break;
2016-03-07 20:57:32 +00:00
}
2016-03-20 22:34:29 +00:00
case WM_PAINT:
{
PAINTSTRUCT ps;
auto hDC = BeginPaint (hWnd, &ps);
auto mascot = LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE (MASCOT));
auto mascotDC = CreateCompatibleDC (hDC);
SelectObject (mascotDC, mascot);
2016-03-24 15:05:47 +00:00
BitBlt (hDC, 0,0, 533, 700, mascotDC, 0, 0, SRCCOPY);
2016-03-20 22:34:29 +00:00
DeleteDC (mascotDC);
DeleteObject (mascot);
EndPaint (hWnd, &ps);
break;
2016-03-24 15:05:47 +00:00
}
2016-03-07 20:57:32 +00:00
}
2016-03-09 19:41:14 +00:00
return DefWindowProc( hWnd, uMsg, wParam, lParam);
2016-03-07 19:54:57 +00:00
}
2016-03-09 19:41:14 +00:00
bool StartWin32App ()
2016-03-07 19:54:57 +00:00
{
2016-03-09 19:41:14 +00:00
if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
{
MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
return false;
}
// register main window
auto hInst = GetModuleHandle(NULL);
WNDCLASSEX wclx;
memset (&wclx, 0, sizeof(wclx));
wclx.cbSize = sizeof(wclx);
wclx.style = 0;
wclx.lpfnWndProc = WndProc;
wclx.cbClsExtra = 0;
wclx.cbWndExtra = 0;
wclx.hInstance = hInst;
wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON));
2016-03-09 19:41:14 +00:00
wclx.hCursor = LoadCursor (NULL, IDC_ARROW);
wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wclx.lpszMenuName = NULL;
wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
RegisterClassEx (&wclx);
// create new window
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 549, 738, NULL, NULL, hInst, NULL))
2016-03-09 19:41:14 +00:00
{
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false;
}
return true;
2016-03-07 19:54:57 +00:00
}
2016-03-09 19:41:14 +00:00
int RunWin32App ()
2016-03-07 19:54:57 +00:00
{
2016-03-09 19:41:14 +00:00
MSG msg;
while (GetMessage (&msg, NULL, 0, 0 ))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
2016-03-07 19:54:57 +00:00
}
2016-03-09 19:41:14 +00:00
void StopWin32App ()
2016-03-07 19:54:57 +00:00
{
2016-03-09 19:41:14 +00:00
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
2016-03-07 19:54:57 +00:00
}
2016-03-09 19:41:14 +00:00
}
}