//+------------------------------------------------------------------+ //| InputResizerEA.mq4 | //| Copyright © 2011, MaryJane | //+------------------------------------------------------------------+ #property copyright "Copyright © 2011, MaryJane" #property link "http://codebase.mql4.com/7657" #import "user32.dll" int GetForegroundWindow(); int FindWindowA(string lpClassName, string lpWindowName); int FindWindowExA(int hwndParent, int hwndChildAfter, string lpszClass, string lpszWindow); int GetWindowRect(int hWnd, int rect[4]); int GetClientRect(int hWnd, int rect[4]); int SetWindowLongA(int hWnd,int nIndex, int dwNewLong); int GetWindowLongA(int hWnd,int nIndex); int GetSystemMenu(int hWnd, bool bRevert); int InsertMenuA(int hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem); int SetWindowPos(int hWnd, int hWndInsertAfter,int X, int Y, int cx, int cy, int uFlags); int GetParent(int hWnd); int GetWindowTextA(int hWnd, string lpString, int nMaxCount); int ShowWindow(int hWnd, int nCmdShow); int GetClassNameA(int hWnd, string lpClassName, int nMaxCount); int GetDlgCtrlID(int hWnd); int GetDlgItem(int hDlg, int nIDDlgItem); bool IsZoomed(int hWnd); bool InvalidateRect(int hWnd, int rect[4], bool bErase); #import #define GWL_STYLE -16 #define WS_SIZEBOX 0x00040000 #define WS_MINIMIZEBOX 0x00020000 #define WS_MAXIMIZEBOX 0x00010000 #define MF_STRING 0x00000000 #define MF_BYPOSITION 0x00000400 #define SW_MAXIMIZE 0x0003 #define SC_SIZE 0xF000 #define SC_MAXIMIZE 0xF030 #define SC_MINIMIZE 0xF020 #define SC_RESTORE 0xF120 #define SWP_NOSIZE 0x0001 #define SWP_NOMOVE 0x0002 #define SWP_NOZORDER 0x0004 #define SWP_NOACTIVATE 0x0010 #define CID_IDBOX 0x0000 #define CID_OK 0x0001 #define CID_CANCEL 0x0002 #define CID_RESET 0x3021 #define CID_TAB 0x3020 #define CID_LIST_ST 0x054D #define CID_LOAD_ST 0x0FAB #define CID_SAVE_ST 0x0FAC #define CID_LIST_EX 0x0567 #define CID_LOAD_EX 0x0FAD #define CID_SAVE_EX 0x0FAE extern bool RememberSize = true; extern bool Individual = true; extern bool InitMaximized = false; extern bool InitCustom = true; extern int initX = 200; extern int initY = 200; extern int initWidth = 350; extern int initHeight = 450; extern int SleepTime = 300; extern bool WeekendMode = false; //+--------------------------------------------------------------------------------------+ void init(){if (!IsDllsAllowed()) Alert("InputResizerEA: DLLs not allowed!"); if (WeekendMode) start();} //+--------------------------------------------------------------------------------------+ void deinit(){} //+--------------------------------------------------------------------------------------+ void start() { static int x , y, xc, yc, oxd, oyd, cxd, rxd, tx, ty, px, py; static int gx, gy, lx, ly, lxd, lyd, sxd, syd; static int r[4], s[4]; static int r0, r1, r2, r3, m, pWnd; static int ok, cancel, reset, tab, list, load, save, idbox, pidbox; static string gvName, gvAdd; static bool resizable; while (true) // We start an infinite loop { // We determine the active (topmost) window int fWnd = GetForegroundWindow(); string cName = "123456789012345678901234567890"; GetClassNameA(GetParent(fWnd), cName, 30); if (cName == "MetaQuotes::MetaTrader::4.00" || cName == "#32770") { // Parent = MT4 or another dialog box cName = "1234567"; GetClassNameA(fWnd, cName, 7); if (cName == "#32770") {// Yes, it is a dialog box, so let's try to get further handles.. idbox = GetDlgItem(fWnd, CID_IDBOX); ok = GetDlgItem(fWnd, CID_OK); cancel = GetDlgItem(fWnd, CID_CANCEL); reset = GetDlgItem(fWnd, CID_RESET); tab = GetDlgItem(fWnd, CID_TAB); if (idbox && ok && cancel && reset && tab) { // Yes, all those elements are present so let's explore the idbox list = FindWindowExA(idbox, 0, "SysListView32", "list1"); switch (GetDlgCtrlID(list)) { case CID_LIST_ST: {load = GetDlgItem(idbox, CID_LOAD_ST); save = GetDlgItem(idbox, CID_SAVE_ST); break;} case CID_LIST_EX: {load = GetDlgItem(idbox, CID_LOAD_EX); save = GetDlgItem(idbox, CID_SAVE_EX); break;} default: {list = 0; load = 0; save = 0;} } if (list != 0) pWnd = fWnd; // a new window was found. } } } if (pWnd == fWnd) // so if we caught a window... { if (!resizable) // it's not resizable until we do it: { // This adds sizable border, minimize and maximize box.Context help question mark in // window caption disappears - the styles can't coexist. SetWindowLongA(pWnd, GWL_STYLE, GetWindowLongA(pWnd, GWL_STYLE) | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); // The above alone doesn't do, the window has to have the items in right-click-on // titlebar menu: int menu = GetSystemMenu(pWnd, false); InsertMenuA(menu, 1, MF_BYPOSITION | MF_STRING, SC_SIZE, "Size"); InsertMenuA(menu, 1, MF_BYPOSITION | MF_STRING, SC_MAXIMIZE, "Maximize"); InsertMenuA(menu, 1, MF_BYPOSITION | MF_STRING, SC_MINIMIZE, "Minimize"); InsertMenuA(menu, 1, MF_BYPOSITION | MF_STRING, SC_RESTORE, "Restore"); // Now our window is sizable with mouse, but since the WM_XXX messages are not parsed // by MT4 (everything inside stays at its place, we have to take care of it. // Now we take all necessary coordinates of inside controls realtive to parent // window as long as it's in original size (hence so many int variables) GetWindowRect(pWnd, r); GetWindowRect(ok, s); oxd = r[2] - s[0]; oyd = r[3] - s[1]; GetWindowRect(cancel, s); cxd = r[2] - s[0]; GetWindowRect(reset, s); rxd = r[2] - s[0]; GetWindowRect(tab, s); tx = s[2] - s[0]; ty = s[3] - s[1]; GetWindowRect(idbox, s); gx = s[2] - s[0]; gy = s[3] - s[1]; GetWindowRect(list, s); lx = s[2] - s[0]; ly = s[3] - s[1]; GetWindowRect(load, s); lxd = r[2] - s[0]; lyd = r[3] - s[1]; GetWindowRect(save, s); sxd = r[2] - s[0]; syd = r[3] - s[1]; GetClientRect(pWnd, s); xc = s[2]; yc = s[3]; // ..before we leave this stage, let's check if we have some memories of this guy if (RememberSize) { gvName = "iRes_"; if (Individual) // one for all ar one for one?! { // ridiculously long empty string should accomodate looooooooooooooooooooongest robot names ;-) gvAdd = " "; GetWindowTextA(pWnd, gvAdd, 50); // retrieve EA/indicator name gvName = gvName + StringTrimRight(gvAdd) +"_"; // add name to global variable name } // let's check if we know that guy if (GlobalVariableCheck(gvName + "r0")) { // if r0 there, other three musketeers will be there too so let's get 'em all: r0 = GlobalVariableGet(gvName + "r0"); r1 = GlobalVariableGet(gvName + "r1"); r2 = GlobalVariableGet(gvName + "r2"); r3 = GlobalVariableGet(gvName + "r3"); m = GlobalVariableGet(gvName + "m"); // now let's put the guy into former shape: if (m == 1) ShowWindow(pWnd, SW_MAXIMIZE); // if maxed previously, just re-max else SetWindowPos(pWnd, 0, r0, r1, r2-r0, r3-r1, SWP_NOZORDER | SWP_NOACTIVATE); } else { // normally we store, but this is firstttime so apply defaults, if any: if (InitMaximized) ShowWindow(pWnd, SW_MAXIMIZE); else if (InitCustom) SetWindowPos(pWnd, 0, initX, initY, initX + initWidth, initY + initHeight, SWP_NOZORDER | SWP_NOACTIVATE); } } else // ..if we don't store anything, let's set defaults, if any: { if (InitMaximized) ShowWindow(pWnd, SW_MAXIMIZE); else if (InitCustom) SetWindowPos(pWnd, 0, initX, initY, initX + initWidth, initY + initHeight, SWP_NOZORDER | SWP_NOACTIVATE); } // This causes the box to redraw, otherwise we get artefacts InvalidateRect(pWnd, s, true); px = 0; py = 0; // reset comparators // ..and that's for us to know this round was done: resizable = true; } // Now we get position and dimensions of the window on every pass GetWindowRect(pWnd, r); GetClientRect(pWnd, s); x = s[2]; y = s[3]; // We're lurkin' for any change: if (x != px || y != py || r0 != r[0] || r1 != r[1] || idbox != pidbox) { if (x != px || y != py || idbox != pidbox) { // and if there's a change in dimension, we move buttons and resize the child box and the // list form inside: if (ok != 0) SetWindowPos(ok, 0, x-oxd+4, y-oyd+4, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); if (cancel != 0) SetWindowPos(cancel, 0, x-cxd+4, y-oyd+4, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); if (reset != 0) SetWindowPos(reset, 0, x-rxd+4, y-oyd+4, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); if (tab != 0) SetWindowPos(tab, 0, 0, 0, tx + x - xc, ty + y - yc, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); if (idbox != 0) SetWindowPos(idbox, 0, 0, 0, gx + x - xc, gy + y - yc, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); if (list != 0) SetWindowPos(list, 0, 0, 0, lx + x - xc, ly + y - yc, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); if (load != 0) SetWindowPos(load, 0, x-lxd-7, y-lyd-25, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); if (save != 0) SetWindowPos(save, 0, x-sxd-7, y-syd-25, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); // next time no change unless really changed: px = x; py = y; } if (RememberSize) { // store last known resized position and size on ANY change GetWindowRect(pWnd, r); GlobalVariableSet(gvName + "r0", r[0]); GlobalVariableSet(gvName + "r1", r[1]); GlobalVariableSet(gvName + "r2", r[2]); GlobalVariableSet(gvName + "r3", r[3]); GlobalVariableSet(gvName + "m", IsZoomed(pWnd)); } // This causes the box to redraw, otherwise we get artefacts InvalidateRect(pWnd, s, true); // next time no change unless really changed: px = x; py = y; r0 = r[0]; r1 = r[1]; pidbox = idbox; } } else resizable = false; // if there's no window (has been closed), // next time we'll have to resize a new one if (Period() == PERIOD_MN1) break; // 300-500 ms does not eat resources but still warrants prompt reaction: Sleep(SleepTime); } }