Es macht folgendes:
Wenn ein Spiel als Beispiel nur fixierte Fenster anbietet und man im Fenstermodus spielen will, aber trotzdem Vollbild haben möchte, dann ist das Programm perfekt dafür.
Es ist ein Fenster ohne Border und in der Größe des Desktops. So fühlt es sich Vollbild an, ist aber keiner. So kann man schnell und leicht raustabben.
Manche Spiele verhindern das allerdings indem sie die Windowsnachricht WM_SIZE blockieren.
Man sollte auch nicht eine 4:3 Auflösung nehmen und die dann auf 16:10 strecken oder so. Das sieht dann entsprechend scheisse aus. Die DirectX/OpenGL Matrizen kann ich damit leider nicht manipulieren.
Wie funzt es?
Starten und dann habt ihr im systray ein icon. Das rechtsklicken und wenn das Spiel nicht Anarchy Online heisst, dort den Fensternamen eingeben. Vorsicht, das ganze ist case-sensitive.
http://code.google.com/p/aomover/
Der Code ist recht simpel:
Code: Alles auswählen
/*
Project AOMover
Copyright 2010 Scorcher24
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Scorcher24
Scorcher24@gmail.com
*/
#ifndef STDAFX_HPP
#define STDAFX_HPP
//////////////////////////////////////////////////////////////////////////
// wxWidgets Includes
//////////////////////////////////////////////////////////////////////////
#include <wx/wx.h>
#include <wx/taskbar.h>
#include <wx/html/htmlwin.h>
#include <wx/xml/xml.h>
#include <wx/textdlg.h>
//////////////////////////////////////////////////////////////////////////
// STL Includes
//////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <list>
//////////////////////////////////////////////////////////////////////////
// OS specific includes
//////////////////////////////////////////////////////////////////////////
#include <process.h>
#endif // STDAFX_HPP
Code: Alles auswählen
/*
Project AOMover
Copyright 2010 Scorcher24
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Scorcher24
Scorcher24@gmail.com
*/
#include "stdafx.hpp"
#include "wxwin16x16.xpm"
namespace AOMover{
//////////////////////////////////////////////////////////////////////////
// Forwards
//////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumWindowCallback(HWND hWindow, LPARAM param);
class Tray;
//////////////////////////////////////////////////////////////////////////
// Enum with all ids for this program
//////////////////////////////////////////////////////////////////////////
enum MenuId
{
ID_CLOSE = wxID_HIGHEST + 1,
ID_ABOUT,
ID_RESIZE_TIMER,
ID_CONFIGURE,
ID_MOVE,
ID_ENTER_WINDOW_NAME,
};
//////////////////////////////////////////////////////////////////////////
// Custom WindowHandle which keeps track of the HWND and the Process ID.
//////////////////////////////////////////////////////////////////////////
struct TWindowHandle
{
TWindowHandle() :
hWindow(NULL), pid(0)
{}
HWND hWindow;
DWORD pid;
};
//////////////////////////////////////////////////////////////////////////
// Metrics of the System
//////////////////////////////////////////////////////////////////////////
struct AbsoluteMetrics
{
AbsoluteMetrics()
: x(0), y(0)
{}
int x;
int y;
};
//////////////////////////////////////////////////////////////////////////
// Struct which is passed to the thread, containing necessary information
//////////////////////////////////////////////////////////////////////////
struct ThreadInfo
{
ThreadInfo() :
tray(NULL), hProcess(NULL), pid(0)
{}
Tray* tray;
HANDLE hProcess;
DWORD pid;
};
//////////////////////////////////////////////////////////////////////////
// Callback for std::for_each
//////////////////////////////////////////////////////////////////////////
void for_each_thread(HANDLE hThread)
{
CloseHandle(hThread);
}
//////////////////////////////////////////////////////////////////////////
// HTML Window Implementation for some tweaking.
//////////////////////////////////////////////////////////////////////////
class HtmlWindow : public wxHtmlWindow
{
public:
HtmlWindow(wxWindow* parent, int id)
: wxHtmlWindow(parent, id)
{}
protected:
//////////////////////////////////////////////////////////////////////////
// Opens the clicked link in browser..
// This is a rather easy protection, but well if someone wants to make
// this program rogue :|, the code is available anyway....
virtual void OnLinkClicked(const wxHtmlLinkInfo & link)
{
if ( link.GetHref() == "http://wxwidgets.org" ||
link.GetHref() == "http://anarchy-online.com")
{
wxLaunchDefaultBrowser(link.GetHref(), 0);
};
}
};
//////////////////////////////////////////////////////////////////////////
// Class representing the tray icon which is the only thing the user
// will see from this program except maybe a future settings dialog.
//////////////////////////////////////////////////////////////////////////
class Tray : public wxTaskBarIcon
{
typedef std::list<TWindowHandle> TWindowList;
typedef std::list<HANDLE> TThreadList;
public:
Tray(wxWindow* parent)
: wxTaskBarIcon(), m_parent(parent), m_window_name("Anarchy Online")
{}
virtual ~Tray()
{
if ( IsIconInstalled() )
{
RemoveIcon();
}
}
//////////////////////////////////////////////////////////////////////////
// Adds an entry, avoids doubles
//////////////////////////////////////////////////////////////////////////
bool AddEntry(TWindowHandle handle)
{
TWindowList::iterator it = m_window_list.begin();
for( it; it != m_window_list.end(); it++ )
{
if ( handle.hWindow == it->hWindow && handle.pid == it->pid )
{
return false;
}
}
m_window_list.push_back(handle);
return true;
}
//////////////////////////////////////////////////////////////////////////
// Removes an entry from the list by its pid
//////////////////////////////////////////////////////////////////////////
void RemoveEntry(DWORD pid)
{
TWindowList::iterator it = m_window_list.begin();
for( it; it != m_window_list.end(); it++ )
{
if ( it->pid == pid )
{
it = m_window_list.erase(it);
if ( it == m_window_list.end() )
return;
}
}
}
//////////////////////////////////////////////////////////////////////////
// Adds a threadhandle to the list so we can delete it later.
//////////////////////////////////////////////////////////////////////////
void AddThread(HANDLE hThread)
{
m_threadList.push_back(hThread);
}
//////////////////////////////////////////////////////////////////////////
// #define replacement to have the name of the window on a central place.
//////////////////////////////////////////////////////////////////////////
wxString GetAnarchyWindowName()
{
return m_window_name;
}
protected:
//////////////////////////////////////////////////////////////////////////
// Creates the popupmenu for the trayicon
//////////////////////////////////////////////////////////////////////////
virtual wxMenu* CreatePopupMenu()
{
wxMenu* menu = new wxMenu();
FindAnarchy();
TWindowList::iterator it = m_window_list.begin();
int i = 0;
for( it; it != m_window_list.end(); it++ )
{
wxString txt;
txt.Printf("AO - PID # %i", it->pid);
menu->Append(ID_MOVE+i, txt);
i++;
}
menu->AppendSeparator();
menu->Append(ID_ABOUT, _("About.."));
menu->AppendSeparator();
menu->Append(ID_ENTER_WINDOW_NAME, _("Enter window name"));
menu->AppendSeparator();
menu->Append(ID_CLOSE, _("Exit"));
menu->SetEventHandler(this);
return menu;
}
//////////////////////////////////////////////////////////////////////////
// Closes the dummy parent frame which will kill the app.
//////////////////////////////////////////////////////////////////////////
void OnMenuClose(wxCommandEvent&)
{
std::for_each(m_threadList.begin(), m_threadList.end(), for_each_thread);
m_parent->Close(true);
}
//////////////////////////////////////////////////////////////////////////
// Shows the About Dialog
//////////////////////////////////////////////////////////////////////////
void OnAboutDlg(wxCommandEvent&)
{
wxDialog dlg(NULL, wxID_ANY, _("About.."), wxDefaultPosition, wxSize(450,600));
HtmlWindow* html = new HtmlWindow(&dlg, wxID_ANY);
html->LoadFile(wxFileName("data/about.html"));
dlg.ShowModal();
}
//////////////////////////////////////////////////////////////////////////
// Event for moving ao.
//////////////////////////////////////////////////////////////////////////
void OnMenuMove(wxCommandEvent& e)
{
wxMenu* m = (wxMenu*)e.GetEventObject();
int id = e.GetId() - ID_MOVE;
wxString label = m->GetLabelText(e.GetId());
label = label.AfterLast('#');
int pid = atoi(label.mb_str());
MoveAnarchy(FindHWNDByPid(pid));
}
//////////////////////////////////////////////////////////////////////////
// Configures AO for usage with our program.
//////////////////////////////////////////////////////////////////////////
void OnConfigure(wxCommandEvent&)
{
AbsoluteMetrics m = GetAbsoluteUserMetrics();
wxString p = GetAnarchyDirectoryFromRegistry() + wxString("/prefs");
wxFileDialog dlg(NULL,
_("Please select the prefs.xml file from your ao-directory."),
p, "prefs.xml", "XML|*.xml");
if ( dlg.ShowModal() == wxID_OK )
{
wxString prefs = dlg.GetPath();
if ( prefs.IsEmpty() )
{
wxMessageBox(_("You need to select a preference file to continue"), _("Error"), wxICON_ERROR|wxOK);
return;
}
ModifyAOPrefs(prefs, m);
}
}
private:
//////////////////////////////////////////////////////////////////////////
// Looks for all Anarchy Online Windows and enlists them.
//////////////////////////////////////////////////////////////////////////
bool FindAnarchy()
{
EnumWindows((WNDENUMPROC)EnumWindowCallback, (LPARAM)this);
return true;
}
//////////////////////////////////////////////////////////////////////////
// Finds the hwnd of the pid
//////////////////////////////////////////////////////////////////////////
HWND FindHWNDByPid(DWORD pid)
{
TWindowList::iterator it = m_window_list.begin();
for ( it; it != m_window_list.end(); it++ )
{
if ( pid == it->pid )
return it->hWindow;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
// Sizes the corresponding AO-Window
//////////////////////////////////////////////////////////////////////////
void MoveAnarchy(HWND hWindow)
{
if ( IsWindow(hWindow) )
{
RECT rct;
ZeroMemory(&rct, sizeof(rct));
long style = GetWindowLong(hWindow, GWL_STYLE);
SetRect(&rct,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN));
if ( style & WS_POPUP )
{
style &= ~WS_POPUP;
style &= ~WS_MAXIMIZE;
style |= WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU|WS_OVERLAPPED|WS_CLIPSIBLINGS;
}
else
{
style &= ~WS_CAPTION;
style &= ~WS_MINIMIZEBOX;
style &= ~WS_SYSMENU;
style &= ~WS_OVERLAPPED;
style &= ~WS_CLIPSIBLINGS;
style |= (WS_POPUP|WS_MAXIMIZE);
}
SetWindowPos(hWindow, HWND_TOP,rct.left,rct.top,rct.right-rct.left,rct.bottom-rct.top,SWP_FRAMECHANGED|SWP_DRAWFRAME);
SetWindowLong(hWindow, GWL_STYLE, style);
UpdateWindow(hWindow);
}
}
//////////////////////////////////////////////////////////////////////////
// Reads the System Metrics for the Titlebar und the border and returns
// a struct with the values.
//////////////////////////////////////////////////////////////////////////
AbsoluteMetrics GetAbsoluteUserMetrics()
{
AbsoluteMetrics m;
// Get Caption and Bordersize
int caption = GetSystemMetrics(SM_CYCAPTION);
int border = GetSystemMetrics(SM_CXBORDER);
// Get Screensize
int x = GetSystemMetrics(SM_CXSCREEN);
int y = GetSystemMetrics(SM_CYSCREEN);
m.x = x;
m.y = y;
return m;
}
//////////////////////////////////////////////////////////////////////////
// Modifies the prefs.xml for usage with our program
// Tested, works for 18.4
//////////////////////////////////////////////////////////////////////////
bool ModifyAOPrefs(const wxString prefs, AbsoluteMetrics m)
{
wxXmlDocument doc;
if ( !doc.Load(prefs) )
{
wxMessageBox(_("Cannot access '") + prefs + "'", wxMessageBoxCaptionStr, wxOK | wxICON_ERROR);
return false;
}
if ( doc.GetRoot()->GetName() != wxString("Root"))
{
wxMessageBox(_("XML Root not recognized. Abort."), wxMessageBoxCaptionStr, wxOK | wxICON_ERROR);
return false;
}
wxXmlNode* child = doc.GetRoot()->GetChildren();
while ( child )
{
if ( child->GetName() == wxString("Value") )
{
wxXmlAttribute* attribs = child->GetAttributes();
if ( attribs->GetValue() == "DisplayHeight")
{
wxXmlAttribute* value = attribs->GetNext();
wxString v;
v.Printf("%i", m.y );
value->SetValue(v);
}
if ( attribs->GetValue() == "DisplayWidth")
{
wxXmlAttribute* value = attribs->GetNext();
wxString v;
v.Printf("%i", m.x );
value->SetValue(v);
}
}
child = child->GetNext();
}
doc.Save(prefs);
return true;
}
// This works pretty straigth: Tries to read the install dir set by anarchies client on win32.
// If not found, it returns an empty string. On all other platforms it returns an empty string only,
// so we simply check for the string empty or not in the constructor.
wxString GetAnarchyDirectoryFromRegistry()
{
wxString result = wxEmptyString;
#ifdef WIN32
wxRegKey* regKey = new wxRegKey("HKEY_CURRENT_USER\\Software\\Anarchy Online");
if ( regKey->Exists() )
{
wxString temp;
if ( regKey->QueryValue("Install Directory", temp) )
{
result = temp;
}
}
delete regKey;
#endif /* WIN32 */
return result;
}
void OnEnterWindowName(wxCommandEvent&)
{
wxString name = wxGetTextFromUser(_("Enter exact window name"), "aomover", m_window_name, NULL);
if ( !name.empty() )
{
m_window_name = name;
}
}
private:
wxWindow* m_parent;
DECLARE_EVENT_TABLE();
TWindowList m_window_list;
TThreadList m_threadList;
wxString m_window_name;
};
//////////////////////////////////////////////////////////////////////////
// Event Table for the Tray
//////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(Tray, wxTaskBarIcon)
EVT_MENU(ID_CLOSE, Tray::OnMenuClose)
EVT_MENU(ID_MOVE, Tray::OnMenuMove)
EVT_MENU(ID_ABOUT, Tray::OnAboutDlg)
EVT_MENU(ID_ENTER_WINDOW_NAME, Tray::OnEnterWindowName)
// EVT_MENU(ID_CONFIGURE, Tray::OnConfigure) // Disabled, Feature does not work currently.
END_EVENT_TABLE()
//////////////////////////////////////////////////////////////////////////
// Dummy Frame which creates the systray-icon
//////////////////////////////////////////////////////////////////////////
class Frame : public wxFrame
{
public:
Frame()
: wxFrame(NULL, wxID_ANY, "You should never see me")
{
m_tray = new Tray(this);
m_tray->SetIcon(wxIcon(wxwin16x16_xpm));
}
virtual ~Frame()
{
delete m_tray;
}
private:
Tray* m_tray;
};
//////////////////////////////////////////////////////////////////////////
// Thread callback for ao's processes. It waits until ao's ended and
// removes the entry in our list then.
//////////////////////////////////////////////////////////////////////////
void CALLBACK WaitThreadCallback(LPVOID param)
{
ThreadInfo* info = reinterpret_cast<ThreadInfo*>(param);
while ( WaitForSingleObject(info->hProcess, INFINITE) == WAIT_TIMEOUT )
{
Sleep(0);
}
CloseHandle(info->hProcess);
info->tray->RemoveEntry(info->pid);
delete info;
}
//////////////////////////////////////////////////////////////////////////
// Callback for EnumWindows
//////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumWindowCallback(HWND hWindow, LPARAM param)
{
if ( IsWindow(hWindow) )
{
Tray* tray = (Tray*)(param);
wchar_t txt[256];
GetWindowText(hWindow, txt, 256);
if ( tray->GetAnarchyWindowName() == wxString(txt) )
{
DWORD pid;
GetWindowThreadProcessId(hWindow, &pid);
TWindowHandle handle;
handle.pid = pid;
handle.hWindow = hWindow;
if ( tray->AddEntry(handle) )
{
HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
if ( hProcess == NULL )
{
wxMessageBox("Cannot open Process");
}
ThreadInfo* info = new ThreadInfo;
info->hProcess = hProcess;
info->tray = tray;
info->pid = pid;
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaitThreadCallback, info, 0, NULL);
tray->AddThread(hThread);
}
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
// Application Class
//////////////////////////////////////////////////////////////////////////
class App : public wxApp
{
public:
virtual bool OnInit()
{
wxImage::AddHandler(new wxPNGHandler);
Frame* f = new Frame;
f->Show(false);
this->SetTopWindow(f);
return true;
}
};
//////////////////////////////////////////////////////////////////////////
// Macro from wx to create the winmain
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_APP(App)
}; // Namespace
