Skip to content

Commit

Permalink
Notify icon functionality.
Browse files Browse the repository at this point in the history
  • Loading branch information
tarao committed Sep 17, 2010
1 parent 7b6914b commit a134a2f
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.ncb
*.suo
*.aps
mmwnd/out
*.vcproj.*
91 changes: 91 additions & 0 deletions mmwnd/common/profile.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#ifndef GNN_PROFILE_HPP_INCLUDED
#define GNN_PROFILE_HPP_INCLUDED

#include <sstream>
#include "tstring.hpp"

namespace gnn {

#ifdef _WINDOWS

class ini_profile {
public:
static tstring default_path(void) {
tchar path[_MAX_PATH];
tchar drive[_MAX_DRIVE];
tchar dir[_MAX_DIR];
tchar fname[_MAX_FNAME];
::GetModuleFileName(::GetModuleHandle(NULL), path, _MAX_PATH);
_tsplitpath(path, drive, dir, fname, NULL);
_tmakepath(path, drive, dir, fname, _T("ini"));
return path;
}

public:
ini_profile(void):path_(default_path()){}
explicit ini_profile(const tstring& path):path_(path){}
ini_profile(const ini_profile& other):path_(other.path_){}

bool delete_section(const tstring& section) const {
return delete_entry(section, tstring());
}
bool delete_entry(const tstring& section, const tstring& entry) const {
return write_string(section, entry, tstring());
}
bool write_string(const tstring& section, const tstring& entry,
const tstring& value) const {
return ::WritePrivateProfileString(section.c_str(), entry.c_str(),
value.c_str(), path_.c_str()) != 0;
}
tstring read_string(const tstring& section, const tstring& entry,
const tstring& default_=tstring()) const {
enum { buf_len = 4096 };
tchar buf[buf_len];
::GetPrivateProfileString(section.c_str(), entry.c_str(),
default_.c_str(), buf, buf_len, path_.c_str());
return tstring(buf);
}

public:
struct entry {
entry(const tstring& sec_, const tstring& ent_):sec(sec_),ent(ent_){}
tstring sec, ent;
};

protected:
tstring path_;
};

struct ini_profile_entry {
ini_profile_entry(ini_profile& p_, const ini_profile::entry& e_)
:p(p_),e(e_){}
ini_profile& p;
const ini_profile::entry& e;
};
ini_profile_entry operator<<(ini_profile& p, const ini_profile::entry& e) {
return ini_profile_entry(p, e);
}
ini_profile_entry operator>>(ini_profile& p, const ini_profile::entry& e) {
return ini_profile_entry(p, e);
}
template<typename T>
ini_profile_entry& operator<<(ini_profile_entry& p, const T& val) {
std::basic_stringstream<tchar> ss;
ss << val;
p.p.write_string(p.e.sec, p.e.ent, ss.str());
return p;
}
template<typename T>
ini_profile_entry& operator>>(ini_profile_entry& p, T& val) {
std::basic_stringstream<tchar> ss1, ss2;
ss1 << val;
ss2.str(p.p.read_string(p.e.sec, p.e.ent, ss1.str()));
ss2 >> val;
return p;
}

#endif // _WINDOWS

} // namespace gnn

#endif // !GNN_PROFILE_HPP_INCLUDED
1 change: 1 addition & 0 deletions mmwnd/mmwnd.sln
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3B3B0322-3669-44C7-8911-027B0EB4634F}"
ProjectSection(SolutionItems) = preProject
common\logger.hpp = common\logger.hpp
common\profile.hpp = common\profile.hpp
common\tstring.hpp = common\tstring.hpp
EndProjectSection
EndProject
Expand Down
109 changes: 106 additions & 3 deletions mmwnd/mmwnd/mmwnd.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,128 @@
#include "stdafx.h"
#include <shellapi.h>

#include "resource.h"
#define WM_USER_POPUP WM_USER+100

#include "../common/logger.hpp"
using gnn::log;

#include "../common/profile.hpp"
#define PROFILE_ENTRY_NOTIFYICON \
gnn::ini_profile::entry(_T("settings"), _T("notify_icon"))

#include "../mmwndhook/mmwndhook.h"
#include "mmwnd.h"
#include "notifyicon.h"

gnn::ini_profile& profile(void) {
static gnn::ini_profile instance;
return instance;
}

notify_icon& the_notify_icon(void) {
static notify_icon instance;
return instance;
}

HWND init(HINSTANCE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int main(void) {
int main(HINSTANCE instance) {
mmwnd& mm = mmwnd::get();
if (!mm.load()) return 1;
if (!mm.install()) return 2;

::MessageBox(NULL, _T("hook started"), _T("mmwnd"), MB_OK); // FIXME
HWND hwnd;
if (!(hwnd=init(instance))) return 3;

bool use_notify_icon = true;
profile() >> PROFILE_ENTRY_NOTIFYICON >> use_notify_icon;

notify_icon& ni = the_notify_icon();
ni.init(hwnd, 0, WM_USER_POPUP, NULL, _T("mmwnd"));
if (use_notify_icon && !ni.install()) return 4;

MSG msg;
while (::GetMessage(&msg, NULL, 0, 0)) ::DispatchMessage(&msg);

if (!ni.uninstall()) return 5;

return 0;
}

int APIENTRY _tWinMain(HINSTANCE instance, HINSTANCE prev,
LPTSTR cmd, int show) {
UNREFERENCED_PARAMETER(prev);
UNREFERENCED_PARAMETER(cmd);
UNREFERENCED_PARAMETER(show);

log().file(instance);
int status = main();
int status = main(instance);
log() << _T("exit ") << status << std::endl;
return status;
}

HWND init(HINSTANCE instance) {
LPCTSTR class_name = _T("mmwnd.main");

WNDCLASSEX wcex;
wcex.cbSize = sizeof(wcex);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = instance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = class_name;
wcex.hIconSm = NULL;
if (!::RegisterClassEx(&wcex)) return NULL;

DWORD style = WS_CAPTION | WS_DISABLED | WS_CLIPSIBLINGS;
HWND hwnd = ::CreateWindow(class_name, class_name, style, 0, 0, 0, 0,
NULL, NULL, instance, NULL);
if (!hwnd) return NULL;
::ShowWindow(hwnd, SW_HIDE);

return hwnd;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM param1, LPARAM param2) {
switch (msg) {
case WM_COMMAND:
switch (LOWORD(param1)) {
case ID_POPUP_SHOWTRAYICON:
log("hide tray icon");
if (the_notify_icon().uninstall()) {
profile() << PROFILE_ENTRY_NOTIFYICON << false;
}
break;
case ID_POPUP_EXIT:
log("exit from menu");
::PostQuitMessage(0);
break;
}
break;
case WM_USER_POPUP:
if (param2 == WM_RBUTTONUP) {
HINSTANCE instance = ::GetModuleHandle(NULL);
HMENU menu = ::LoadMenu(instance, MAKEINTRESOURCE(IDR_MENU1));
HMENU popup;
if (menu && (popup = ::GetSubMenu(menu, 0))) {
::SetForegroundWindow(hwnd);
POINT pt;
::GetCursorPos(&pt);
::TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
pt.x, pt.y, 0, hwnd, NULL);
::PostMessage(hwnd, WM_NULL, 0, 0);
}
}
break;
default:
return ::DefWindowProc(hwnd, msg, param1, param2);
}
return 0;
}
78 changes: 78 additions & 0 deletions mmwnd/mmwnd/mmwnd.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// ���{�� resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENU
BEGIN
POPUP "popup"
BEGIN
MENUITEM "show &tray icon", ID_POPUP_SHOWTRAYICON, CHECKED
MENUITEM "e&xit", ID_POPUP_EXIT
END
END

#endif // ���{�� resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

12 changes: 12 additions & 0 deletions mmwnd/mmwnd/mmwnd.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@
RelativePath=".\mmwnd.h"
>
</File>
<File
RelativePath=".\notifyicon.h"
>
</File>
<File
RelativePath=".\resource.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
Expand All @@ -222,6 +230,10 @@
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\mmwnd.rc"
>
</File>
</Filter>
</Files>
<Globals>
Expand Down
28 changes: 28 additions & 0 deletions mmwnd/mmwnd/notifyicon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef MMWND_NOTIFYICON_H_INCLUDED
#define MMWND_NOTIFYICON_H_INCLUDED

class notify_icon {
public:
notify_icon(void):installed(false){}
void init(HWND hwnd, UINT id, UINT msg, HICON icon, LPCTSTR tip) {
nid.cbSize = sizeof(nid);
nid.hWnd = hwnd;
nid.uID = id;
nid.uFlags = NIF_MESSAGE | /* NIF_ICON |*/ NIF_TIP;
nid.uCallbackMessage = msg;
nid.hIcon = icon;
lstrcpy(nid.szTip, tip);
}
bool install(void) {
return (installed = (::Shell_NotifyIcon(NIM_ADD, &nid) != 0));
}
bool uninstall(void) {
if (!installed) return true;
return ::Shell_NotifyIcon(NIM_DELETE, &nid) != 0 && !(installed = false);
}
private:
NOTIFYICONDATA nid;
bool installed;
};

#endif // !MMWND_NOTIFYICON_H_INCLUDED
18 changes: 18 additions & 0 deletions mmwnd/mmwnd/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by mmwnd.rc
//
#define IDR_MENU1 101
#define ID_POPUP_EXIT 40001
#define ID_POPUP_SHOWTRAYICON 40002

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

0 comments on commit a134a2f

Please sign in to comment.