diff --git a/args.cpp b/args.cpp index 7e4afc2..aa4320d 100644 --- a/args.cpp +++ b/args.cpp @@ -1,5 +1,30 @@ #include "header.h" +int ParseNum(const char *arg, int &num, int &opts, int pcopt) +{ + char *end; + + if(pcopt == MOVHORZPC) { + if(*arg == 'l') opts |= MOVLEFT, ++arg; + else if(*arg == 'r') opts |= MOVRIGHT, ++arg; + } + else if(pcopt == MOVVERTPC) { + if(*arg == 't') opts |= MOVTOP, ++arg; + else if(*arg == 'b') opts |= MOVBOTTOM, ++arg; + } + else if(pcopt == SIZWIDTHPC) { + if(*arg == 'l' || *arg == 'r') opts |= SIZLEFT, ++arg; + } + else if(pcopt == SIZHEIGHTPC) { + if(*arg == 't' || *arg == 'b') opts |= SIZTOP, ++arg; + } + num = strtol(arg, &end, 10); + if(end == arg) return(1); + if(*end == '%' && end[1] == '\0') opts |= pcopt; + else if(*end != '\0') return(1); + return(0); +} + void ParseArgs(int argc, char *argv[], struct ARGS *a) { register int i; @@ -23,6 +48,8 @@ void ParseArgs(int argc, char *argv[], struct ARGS *a) *a->tasks = (TASK) 0; a->listopts = 0; a->actopts = 0; + a->movopts = 0; + a->sizopts = 0; a->sleep = 0; a->wait = 0; a->wait_ms = -1; @@ -99,10 +126,8 @@ void ParseArgs(int argc, char *argv[], struct ARGS *a) // next two args MUST be the new left and top coords // if( (i+2) < argc) { - a->left = atoi(argv[++i]); - a->top = atoi(argv[++i]); - if( (!a->left) && lstrcmp(argv[i-1], "0") ) Quit(MOVERR); - if( (!a->top) && lstrcmp(argv[i], "0") ) Quit(MOVERR); + if(ParseNum(argv[++i], a->left, a->movopts, MOVHORZPC)) Quit(MOVERR); + if(ParseNum(argv[++i], a->top, a->movopts, MOVVERTPC)) Quit(MOVERR); } else Quit(MOVERR); } @@ -112,10 +137,8 @@ void ParseArgs(int argc, char *argv[], struct ARGS *a) // PushTask(a->tasks, SIZ); if( (i+2) < argc) { - a->width = atoi(argv[++i]); - a->height = atoi(argv[++i]); - if( (!a->width) && lstrcmp(argv[i-1], "0") ) Quit(SIZERR); - if( (!a->height) && lstrcmp(argv[i], "0") ) Quit(SIZERR); + if(ParseNum(argv[++i], a->width, a->sizopts, SIZWIDTHPC)) Quit(SIZERR); + if(ParseNum(argv[++i], a->height, a->sizopts, SIZHEIGHTPC)) Quit(SIZERR); } else Quit(SIZERR); } @@ -312,7 +335,7 @@ void Quit(const int Err) // --1----+----2----+----3----+----4----+----5----+----6----+----7----+----8 "Memory allocation failed", /* MEMERR 0 */ "/MOV command requires left and top arguments", /* MOVERR 1 */ - "/SIZ command requires width and height agrguments", /* SIZERR 2 */ + "/SIZ command requires width and height arguments", /* SIZERR 2 */ "/REN command requires a new caption to be specified", /* RENERR 3 */ "Unrecognized argument(s). Use CMDOW /? for help", /* UNRARG 4 */ "Incompatible argument(s). Use CMDOW /? for help", /* CONARG 5 */ diff --git a/header.h b/header.h index c3b8753..eca63db 100644 --- a/header.h +++ b/header.h @@ -66,6 +66,22 @@ enum ACTOPTS { DONTBLAMEME = 0x0001 /* Allows actions to be performed on more than one window */ }; +enum MOVOPTS { + MOVLEFT = 0x0001, /* Move relative to left of monitor */ + MOVTOP = 0x0002, /* Move relative to top of monitor */ + MOVRIGHT = 0x0004, /* Move relative to right of monitor */ + MOVBOTTOM = 0x0008, /* Move relative to bottom of monitor */ + MOVHORZPC = 0x0010, /* Horizontal move is percentage of monitor width */ + MOVVERTPC = 0x0020, /* Vertical move is percentage of monitor height */ +}; + +enum SIZOPTS { + SIZLEFT = 0x0001, /* Size by moving left edge, not right */ + SIZTOP = 0x0002, /* Size by moving top edge, not bottom */ + SIZWIDTHPC = 0x0004, /* Size relative to monitor width */ + SIZHEIGHTPC = 0x0008, /* Size relative to monitor height */ +}; + struct ARGS { char *caption; /* Caption to list, or operate on */ char *newcapt; /* New caption, used with /REN */ @@ -78,6 +94,8 @@ struct ARGS { int actopts; /* Options for actions upon selected windows */ int left, top; /* Holds coords for moving window */ int width, height; /* Used for resizing a window */ + int movopts; /* Options for moving a window */ + int sizopts; /* Options for sizing a window */ int sleep; /* Sleep milliseconds */ int wait, wait_ms; /* If waiting, and for how long */ char *file; /* File to open/run, used with /RUN */ diff --git a/help.cpp b/help.cpp index 07a6bc9..55eb0d0 100644 --- a/help.cpp +++ b/help.cpp @@ -204,16 +204,21 @@ printf( printf( " /MOV Moves the specified window. The left and top arguments specify the\n" " new position of the left top corner of the window. For level one\n" - " windows this is relative to the desktop, and for child windows this\n" - " is relative to its parent window. Level one windows can be moved off\n" - " the screen using negative coords or coords greater than the desktop\n" - " size. You should not move a minimized or maximized window without\n" - " first restoring it.\n" + " windows this is relative to the desktop (or monitor, if prefixed with\n" + " 'l'eft/'r'ight or 't'op/'b'ottom, and/or suffixed with '%%', which\n" + " moves to a percentage of the width or height), and for child windows\n" + " this is relative to its parent window. Level one windows can be moved\n" + " off the screen using negative coords or coords greater than the\n" + " desktop size. You should not move a minimized or maximized window\n" + " without first restoring it.\n" " /SIZ Resizes the specified window. The width and height arguments specify\n" - " the new absolute width and height. In general, windows cannot be made\n" - " smaller using /SIZ than they could if using conventional methods. You\n" - " should not resize a minimized or maximized window without first\n" - " restoring it.\n"); + " the new absolute width and height, or as a percentage of the monitor\n" + " or parent if suffixed with '%%'. Prefix width with 'l' or 'r' to move\n" + " the left edge, preserving the right; prefix height with 't' or 'b' to\n" + " move the top edge, preserving the bottom. In general, windows cannot\n" + " be made smaller using /SIZ than they could if using conventional\n" + " methods. You should not resize a minimized or maximized window\n" + " without first restoring it.\n"); printf( " /CLS Politely asks the specified window to close. Most applications will\n" " respond to this request, although some may display a message box\n" diff --git a/wlist.cpp b/wlist.cpp index af47bc9..cbbe58e 100644 --- a/wlist.cpp +++ b/wlist.cpp @@ -566,20 +566,59 @@ void RenWin(struct WLIST *w, struct ARGS *a) return; } +// +// Retrieve the bounding rectangle of a window: the monitor's work area for a +// top-level window; otherwise the parent's client area. +// +void GetBounds(struct WLIST *w, RECT &r) +{ + if(w->level > 1) { + GetClientRect(w->parent, &r); + } + else { + HMONITOR monitor = MonitorFromWindow(w->hwnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi; + mi.cbSize = sizeof(mi); + GetMonitorInfo(monitor, &mi); + r = mi.rcWork; + } +} + // // Move window to new top left coords // void MovWin(struct WLIST *w, struct ARGS *a) { - MoveWindow(w->hwnd, a->left, a->top, w->width, w->height, TRUE); + int left = a->left, top = a->top; + if(a->movopts) { + RECT r; + GetBounds(w, r); + if(a->movopts & MOVHORZPC) left = (r.right - r.left) * left / 100; + if(a->movopts & MOVLEFT) left += r.left; + if(a->movopts & MOVRIGHT) left = r.right - left - w->width; + if(a->movopts & MOVVERTPC) top = (r.bottom - r.top) * top / 100; + if(a->movopts & MOVTOP) top += r.top; + if(a->movopts & MOVBOTTOM) top = r.bottom - top - w->height; + } + MoveWindow(w->hwnd, left, top, w->width, w->height, TRUE); } // -// Resize window, to new height and width +// Resize window to new height and width // void SizWin(struct WLIST *w, struct ARGS *a) { - MoveWindow(w->hwnd, w->left, w->top, a->width, a->height, TRUE); + int left = w->left, top = w->top; + int width = a->width, height = a->height; + if(a->sizopts & (SIZWIDTHPC | SIZHEIGHTPC)) { + RECT r; + GetBounds(w, r); + if(a->sizopts & SIZWIDTHPC) width = (r.right - r.left) * width / 100; + if(a->sizopts & SIZHEIGHTPC) height = (r.bottom - r.top) * height / 100; + } + if(a->sizopts & SIZLEFT) left += w->width - width; + if(a->sizopts & SIZTOP) top += w->height - height; + MoveWindow(w->hwnd, left, top, width, height, TRUE); } //