Skip to content

Commit

Permalink
New Option: restrict_movement (true by default).
Browse files Browse the repository at this point in the history
Without this option, mmwnd affects only when a window has created or changed its frame appearance.
  • Loading branch information
tarao committed Sep 19, 2010
1 parent e2b50ca commit aab9bc4
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 44 deletions.
118 changes: 87 additions & 31 deletions mmwnd/common/profile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,42 @@
#define GNN_PROFILE_HPP_INCLUDED

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

namespace gnn {

class iprofile {
public:
virtual ~iprofile(void){}
virtual bool delete_section(const tstring& section)= 0;
virtual bool delete_entry(const tstring& section,
const tstring& entry) = 0;
virtual bool write(const tstring& section, const tstring& entry,
const tstring& value) = 0;
virtual tstring read(const tstring& section, const tstring& entry,
const tstring& default_) = 0;
public:
struct entry {
entry(const tstring& sec_, const tstring& ent_):sec(sec_),ent(ent_){}
tstring sec, ent;
};
};

#ifdef _WINDOWS

class ini_profile {
class ini_profile : public iprofile {
public:
static tstring default_path(void) {
static tstring default_path(HINSTANCE instance=NULL,
const tstring& name = tstring()) {
tchar path[_MAX_PATH];
tchar drive[_MAX_DRIVE];
tchar dir[_MAX_DIR];
tchar fname[_MAX_FNAME];
::GetModuleFileName(::GetModuleHandle(NULL), path, _MAX_PATH);
if (!instance) instance = ::GetModuleHandle(NULL);
::GetModuleFileName(instance, path, _MAX_PATH);
_tsplitpath(path, drive, dir, fname, NULL);
_tmakepath(path, drive, dir, fname, _T("ini"));
_tmakepath(path, drive, dir, name.empty()?fname:name.c_str(), _T("ini"));
return path;
}

Expand All @@ -26,66 +46,102 @@ class ini_profile {
explicit ini_profile(const tstring& path):path_(path){}
ini_profile(const ini_profile& other):path_(other.path_){}

bool delete_section(const tstring& section) const {
void set_path(const tstring& path){ path_ = path; }
void set_path(HINSTANCE instance, const tstring& fname) {
path_ = default_path(instance, fname);
}
tstring get_path(void) const { return path_; }

virtual bool delete_section(const tstring& section) {
return delete_entry(section, tstring());
}
bool delete_entry(const tstring& section, const tstring& entry) const {
return write_string(section, entry, tstring());
virtual bool delete_entry(const tstring& section,
const tstring& entry) {
return write(section, entry, tstring());
}
bool write_string(const tstring& section, const tstring& entry,
const tstring& value) const {
virtual bool write(const tstring& section, const tstring& entry,
const tstring& value) {
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 {
virtual tstring read(const tstring& section, const tstring& entry,
const tstring& default_) {
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);
}

protected:
tstring path_;
};

#endif // _WINDOWS

class cached_profile : public iprofile {
public:
struct entry {
entry(const tstring& sec_, const tstring& ent_):sec(sec_),ent(ent_){}
tstring sec, ent;
};
cached_profile(iprofile& p):p_(p){}
cached_profile(cached_profile& other):p_(other.p_), cache_(other.cache_){}
virtual bool delete_section(const tstring& section) {
cache_.clear();
return p_.delete_section(section);
}
virtual bool delete_entry(const tstring& section,
const tstring& entry) {
cache_.erase(make_entry(section, entry));
return p_.delete_entry(section, entry);
}
virtual bool write(const tstring& section, const tstring& entry,
const tstring& value) {
cache_[make_entry(section, entry)] = value;
return p_.write(section, entry, value);
}
virtual tstring read(const tstring& section, const tstring& entry,
const tstring& default_) {
tstring val = p_.read(section, entry, default_);
tstring ent = make_entry(section, entry);
if (!cache_.count(ent)) const_cast<cache_type&>(cache_)[ent] = val;
return val;
}

protected:
tstring path_;
static tstring make_entry(const tstring& section, const tstring& entry) {
return section + _T("::") + entry;
}
typedef std::map<tstring, tstring> cache_type;
iprofile& p_;
cache_type cache_;
};

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;
struct profile_entry {
profile_entry(iprofile& p_, const iprofile::entry& e_):p(p_),e(e_){}
profile_entry(const profile_entry& other):p(other.p),e(other.e){}
iprofile& p;
const iprofile::entry& e;
};
ini_profile_entry operator<<(ini_profile& p, const ini_profile::entry& e) {
return ini_profile_entry(p, e);
profile_entry operator<<(iprofile& p, const iprofile::entry& e) {
return profile_entry(p, e);
}
ini_profile_entry operator>>(ini_profile& p, const ini_profile::entry& e) {
return ini_profile_entry(p, e);
profile_entry operator>>(iprofile& p, const iprofile::entry& e) {
return profile_entry(p, e);
}
template<typename T>
ini_profile_entry& operator<<(ini_profile_entry& p, const T& val) {
profile_entry& operator<<(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());
p.p.write(p.e.sec, p.e.ent, ss.str());
return p;
}
template<typename T>
ini_profile_entry& operator>>(ini_profile_entry& p, T& val) {
profile_entry& operator>>(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.str(p.p.read(p.e.sec, p.e.ent, ss1.str()));
ss2 >> val;
return p;
}

#endif // _WINDOWS

} // namespace gnn

#endif // !GNN_PROFILE_HPP_INCLUDED
20 changes: 16 additions & 4 deletions mmwnd/mmwnd/mmwnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@
#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 "profile.h"
#include "notifyicon.h"

gnn::ini_profile& profile(void) {
Expand Down Expand Up @@ -99,6 +96,16 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM param1, LPARAM param2) {
switch (msg) {
case WM_COMMAND:
switch (LOWORD(param1)) {
case ID_POPUP_RESTRICTMOVEMENT: {
bool restrict_movement = true;
profile() >> PROFILE_ENTRY_RESTRICTMOVEMENT >> restrict_movement;
restrict_movement = !restrict_movement;
profile() << PROFILE_ENTRY_RESTRICTMOVEMENT << restrict_movement;
mmwnd::get().reinstall();
log() << _T("toggle restrict movement: ")
<< restrict_movement << std::endl;
break;
}
case ID_POPUP_SHOWTRAYICON:
log("hide tray icon");
if (the_notify_icon().uninstall()) {
Expand All @@ -117,6 +124,11 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM param1, LPARAM param2) {
HMENU menu = ::LoadMenu(instance, MAKEINTRESOURCE(IDR_MENU1));
HMENU popup;
if (menu && (popup = ::GetSubMenu(menu, 0))) {
bool restrict_movement = true;
profile() >> PROFILE_ENTRY_RESTRICTMOVEMENT >> restrict_movement;
::CheckMenuItem(popup, ID_POPUP_RESTRICTMOVEMENT,
restrict_movement ? MF_CHECKED : MF_UNCHECKED);

::SetForegroundWindow(hwnd);
POINT pt;
::GetCursorPos(&pt);
Expand Down
1 change: 1 addition & 0 deletions mmwnd/mmwnd/mmwnd.rc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ IDR_MENU1 MENU
BEGIN
POPUP "popup"
BEGIN
MENUITEM "restrict &movement", ID_POPUP_RESTRICTMOVEMENT, CHECKED
MENUITEM "show &tray icon", ID_POPUP_SHOWTRAYICON, CHECKED
MENUITEM "e&xit", ID_POPUP_EXIT
END
Expand Down
4 changes: 4 additions & 0 deletions mmwnd/mmwnd/mmwnd.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@
RelativePath=".\notifyicon.h"
>
</File>
<File
RelativePath=".\profile.h"
>
</File>
<File
RelativePath=".\resource.h"
>
Expand Down
10 changes: 10 additions & 0 deletions mmwnd/mmwnd/profile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef MMWND_PROFILE_H_INCLUDED
#define MMWND_PROFILE_H_INCLUDED

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

#endif // !MMWND_PROFILE_H_INCLUDED
3 changes: 2 additions & 1 deletion mmwnd/mmwnd/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
#define IDI_ICON1 102
#define ID_POPUP_EXIT 40001
#define ID_POPUP_SHOWTRAYICON 40002
#define ID_POPUP_RESTRICTMOVEMENT 40003

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_COMMAND_VALUE 40004
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
Expand Down
13 changes: 13 additions & 0 deletions mmwnd/mmwndhook/mmwndhook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
using gnn::log;

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

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

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

#include "mmwndhook_impl.h"

#ifdef _MANAGED
Expand All @@ -13,6 +25,7 @@ using gnn::log;
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
log().file(module);
raw_profile().set_path(module, _T("mmwnd"));
mmwndhook_impl::get()->set_module_handle(module);
}
return TRUE;
Expand Down
24 changes: 16 additions & 8 deletions mmwnd/mmwndhook/mmwndhook_impl.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
#ifndef MMWNDHOOK_IMPL_H_INCLUDED
#define MMWNDHOOK_IMPL_H_INCLUDED

bool adjust_pos(HWND hwnd);
bool adjust_pos(HWND, UINT);

class mmwndhook_impl : public mmwndhook {
public:
static LRESULT CALLBACK hook_proc(int code, WPARAM param1, LPARAM param2) {
CWPRETSTRUCT* p = reinterpret_cast<CWPRETSTRUCT*>(param2);
switch (p->message) {
case WM_WINDOWPOSCHANGED:
case WM_WINDOWPOSCHANGED: {
bool restrict_movement = true;
profile() >> PROFILE_ENTRY_RESTRICTMOVEMENT >> restrict_movement;
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(p->lParam);
if (!restrict_movement && !(wp->flags & SWP_FRAMECHANGED)) break;
}
case WM_CREATE:
adjust_pos(p->hwnd);
adjust_pos(p->hwnd, p->message);
break;
}
return ::CallNextHookEx(NULL, code, param1, param2);
Expand Down Expand Up @@ -60,11 +65,12 @@ gnn::tstring to_s(const RECT& rect) {

#endif // _DEBUG

bool adjust_pos(HWND hwnd) {
bool adjust_pos(HWND hwnd, UINT msg) {
WINDOWINFO wi;
wi.cbSize = sizeof(wi);
::GetWindowInfo(hwnd, &wi);
if (!(wi.dwStyle & WS_VISIBLE)) return false; // ignore invisible window
if (!(wi.dwStyle & WS_BORDER)) return false; // ignore no border

RECT rect;
::GetWindowRect(hwnd, &rect);
Expand All @@ -91,7 +97,7 @@ bool adjust_pos(HWND hwnd) {
if ((mon1 = ::MonitorFromPoint(pt1, MONITOR_DEFAULTTONULL)) &&
(mon2 = ::MonitorFromPoint(pt2, MONITOR_DEFAULTTONULL))) {
if (wi.dwExStyle & WS_EX_TOPMOST) {
return false; // top most window will show over the taskbar
return false; // top most window shows over the taskbar
}
MONITORINFO mi1, mi2;
mi1.cbSize = mi2.cbSize = sizeof(MONITORINFO);
Expand Down Expand Up @@ -119,7 +125,6 @@ bool adjust_pos(HWND hwnd) {
HWND desktop = ::GetDesktopWindow();
if (hwnd == desktop) return false;


// ignore descendants of taskbar
HWND root = NULL;
HWND tmp = hwnd;
Expand All @@ -133,10 +138,13 @@ bool adjust_pos(HWND hwnd) {
::MoveWindow(hwnd, pt.x, pt.y, width, height, TRUE);

#ifdef _DEBUG
TCHAR class_name[_MAX_PATH];
::GetClassName(hwnd, class_name, _MAX_PATH);
std::basic_stringstream<gnn::tchar> ss;
ss << std::endl << _T(" ") << _T("[hwnd] 0x") << std::setbase(16) << hwnd;
ss << std::endl << _T(" ") << _T("[class] ") << class_name;
ss << std::endl << _T(" ") << _T("[HWND] 0x") << std::setbase(16) << hwnd;
ss << std::endl << _T(" ") << _T("[msg] 0x") << std::setbase(16) << msg;
ss << std::endl << _T(" ") << _T("[pos] ") << to_s(rect);
ss << std::endl << _T(" ") << _T("[mon] ") << to_s(mi.rcWork);
RECT dst = { pt.x, pt.y, pt.x+width, pt.y+height };
ss << std::endl << _T(" ") << _T("[dst] ") << to_s(dst);
::GetWindowRect(hwnd, &rect);
Expand Down
1 change: 1 addition & 0 deletions mmwnd/mmwndhook/stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>

#endif // !STDAFX_H_INCLUDED

0 comments on commit aab9bc4

Please sign in to comment.