|
|
/****************************************************************************
PROGRAM: xerox.c
PURPOSE: Copies keyboard input to multiple target windows.
****************************************************************************/
#include "xerox.h"
#include "string.h"
#include "group.h"
#include "pos.h"
#include "stdio.h"
#define cmPaste 0xFFF1
#define VK_V 0x56 //Virtual Key V
#define KEY_IS_DOWN 0x8000
// #define TESTING
static char pszMainWindowClass[] = "Main Window Class"; char szTitle[] = "Xerox";
HANDLE hInst; HACCEL hAccel;
HWND hwndMain; HWND hwndList; // handle of listbox containing targets.
BOOL InitApplication(HANDLE); BOOL InitInstance(HANDLE, INT);
INT_PTR APIENTRY MainWndProc(HWND, UINT, WPARAM, LPARAM); BOOL PostToTargets(HWND, UINT, WPARAM, LPARAM);
INT_PTR APIENTRY WindowListDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL WindowListDlgInit(HWND); BOOL CALLBACK WindowListWindowEnum(HWND, LPARAM); INT WindowListDlgEnd(HWND, HWND*);
INT_PTR APIENTRY AboutDlgProc(HWND, UINT, WPARAM, LPARAM); INT_PTR APIENTRY GroupAddDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR APIENTRY GroupDeleteDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR APIENTRY GroupSelectDlgProc(HWND hDlg, UINT msg, WPARAM wParam,LPARAM lParam);
/****************************************************************************
FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
PURPOSE: calls initialization function, processes message loop
****************************************************************************/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { MSG Message;
if (!hPrevInstance) { if (!InitApplication(hInstance)) { return (FALSE); } }
if (!InitInstance(hInstance, nCmdShow)) { return (FALSE); }
while (GetMessage(&Message, NULL, 0, 0)) { if (!TranslateAccelerator(hwndMain, hAccel, &Message)) { TranslateMessage(&Message); DispatchMessage(&Message); } }
SaveGroups(); FreeGroups(); return ((int)Message.wParam); }
/****************************************************************************
FUNCTION: InitApplication(HANDLE)
PURPOSE: Initializes window data and registers window class
****************************************************************************/
BOOL InitApplication(HANDLE hInstance) { WNDCLASS wc;
// Register the main window class
wc.style = 0; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = (LPSTR)IDM_MAINMENU; wc.lpszClassName = pszMainWindowClass;
return (RegisterClass(&wc)); }
/****************************************************************************
FUNCTION: InitInstance(HANDLE, int)
PURPOSE: Saves instance handle and creates main window
****************************************************************************/
BOOL InitInstance(HANDLE hInstance, INT nCmdShow) { RECT rc; BOOL fLastPosSet;
LoadGroups();
// Store instance in global
hInst = hInstance;
hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_ACCEL)); fLastPosSet = GetLastPosition(&rc);
// Create the main window
hwndMain = CreateWindow( pszMainWindowClass, szTitle, WS_OVERLAPPEDWINDOW, fLastPosSet ? rc.left : CW_USEDEFAULT, fLastPosSet ? rc.top : CW_USEDEFAULT, fLastPosSet ? rc.right - rc.left : CW_USEDEFAULT, fLastPosSet ? rc.bottom - rc.top : CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (hwndMain == NULL) { return(FALSE); }
if (GetCurrentGroup() != NULL) { SelectGroupDefinition(GetCurrentGroup(), hwndList, FALSE); }
ShowWindow(hwndMain, nCmdShow); UpdateWindow(hwndMain);
return (TRUE); }
/****************************************************************************
FUNCTION: MainWndProc(HWND, UINT, WPARAM, LONG)
PURPOSE: Processes messages for main window
COMMENTS:
****************************************************************************/
INT_PTR APIENTRY MainWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { HMENU hMenu; BOOL Result; RECT rcWindow; WINDOWPLACEMENT wpWndPlacement; HWND hwndAdd, hwndDelete; CHAR string[MAX_STRING_BYTES]; INT ItemDelete;
INT TargetCount; INT Index; HWND hwndTarget; WINDOWPLACEMENT wndpl; INT NumberOfItems = 0; INT counter; HWND WindowHandleList[MAX_WINDOWS]; INT SelectedWindows[MAX_WINDOWS];
switch (message) {
case WM_CREATE:
GetWindowRect(hwnd, &rcWindow);
if (GetCurrentGroup() != NULL) { wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup()); SetWindowText(hwnd, string); }
hwndList = CreateWindow( "LISTBOX", NULL, // Title
WS_CHILD | WS_VISIBLE | LBS_MULTIPLESEL, 0, 0, // x,y
rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, hwnd, // owner
NULL, // menu
hInst, NULL);
//
// Attach all threads to our input state
//
#ifndef TESTING
Result = AttachThreadInput( 0, GetCurrentThreadId(), TRUE // Attaching
); if (!Result) { } #endif // !TESTING
return(0); // Continue creating window
case WM_INITMENU: hMenu = (HMENU)wParam; EnableMenuItem(hMenu, IDM_GROUPRSTWIN, GetCurrentGroup() != NULL ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu, IDM_GROUPMINWIN, GetCurrentGroup() != NULL ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu, IDM_GROUPDELETE, CountGroups() ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu, IDM_GROUPSELECT, CountGroups() ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu, IDM_TARGETDELETE, (SendMessage(hwndList, LB_GETCURSEL, 0, 0) != LB_ERR) ? MF_ENABLED : MF_GRAYED); break;
case WM_SIZE:
//
// Keep the listbox in sync with the main window
//
MoveWindow(hwndList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); return(0);
case WM_COMMAND: switch (LOWORD(wParam)) {
/*
* Restore the windows of the current group. Assumes that everything * can be restored. */ case IDM_GROUPRSTWIN:
TargetCount = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0); if (TargetCount == LB_ERR) { break; }
for (Index = 0; Index < TargetCount; Index ++) { hwndTarget = (HWND)SendMessage(hwndList, LB_GETITEMDATA, Index, 0);
ShowWindow(hwndTarget, SW_RESTORE); }
SetFocus(hwndMain); break;
/*
* Minimize the windows of the current group. Assumes that everything * can be minimized. */ case IDM_GROUPMINWIN:
TargetCount = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0); if (TargetCount == LB_ERR) { break; }
for (Index = 0; Index < TargetCount; Index ++) { hwndTarget = (HWND)SendMessage(hwndList, LB_GETITEMDATA, Index, 0);
ShowWindow(hwndTarget, SW_MINIMIZE); } break;
case IDM_TARGETADD:
hwndAdd = (HWND)DialogBox(hInst,(LPSTR)IDD_WINDOWLIST, hwnd, WindowListDlgProc);
SetNoCurrentGroup(hwnd, szTitle); break;
case IDM_TARGETDELETE:
NumberOfItems = (INT)SendMessage(hwndList, LB_GETSELCOUNT, 0, 0);
if (SendMessage(hwndList, LB_GETSELITEMS, (WPARAM)NumberOfItems, (LPARAM)SelectedWindows) != NumberOfItems) { break; }
if (NumberOfItems > 0) { counter = NumberOfItems; while ( counter-- > 0) {
SendMessage(hwndList, LB_DELETESTRING, (WPARAM)WindowHandleList[counter], 0); } } SendMessage(hwndList, LB_SETSEL, 1, (LPARAM)(max(0, WindowHandleList[0] - 1))); SetNoCurrentGroup(hwnd, szTitle); break;
case IDM_GROUPADD: //
// Defines a 'group' of processes to equal the current target list
//
if (((LPSTR)DialogBox(hInst, MAKEINTRESOURCE(IDD_GROUPADD), hwnd, GroupAddDlgProc)) != NULL) {
wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup()); SetWindowText(hwnd, string); } break;
case IDM_GROUPDELETE: DialogBox(hInst, MAKEINTRESOURCE(IDD_GROUPDELETE), hwnd, GroupDeleteDlgProc);
if (GetCurrentGroup() == NULL) { SetWindowText(hwnd, szTitle); } else { SelectGroupDefinition(GetCurrentGroup(), hwndList, FALSE); wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup()); SetWindowText(hwnd, string); } break;
case IDM_GROUPSELECT: if (DialogBox(hInst, MAKEINTRESOURCE(IDD_GROUPSELECT), hwnd, GroupSelectDlgProc)) {
wsprintf(string, "%s - (%s)", szTitle, GetCurrentGroup()); SetWindowText(hwnd, string); } break;
case IDM_REFRESHITEMS: SelectGroupDefinition(GetCurrentGroup(), hwndList, FALSE); break;
case IDM_ABOUT: DialogBox(hInst,(LPSTR)IDD_ABOUT, hwnd, AboutDlgProc); break;
default: break; } break;
case WM_DESTROY:
//
// Detach all threads from our input state
//
#ifndef TESTING
Result = AttachThreadInput( 0, GetCurrentThreadId(), FALSE // Detaching
); if (!Result) { } #endif // !TESTING
GetWindowPlacement( hwndMain, &wpWndPlacement ); SetLastPosition(&wpWndPlacement.rcNormalPosition); PostQuitMessage(0); break;
case WM_PARENTNOTIFY:
if (LOWORD(wParam) == WM_RBUTTONDOWN) { // send cmPaste message.
PostToTargets(hwndList,WM_SYSCOMMAND,cmPaste,lParam); } break;
case WM_NCRBUTTONDOWN:
// send cmPaste message.
PostToTargets(hwndList,WM_SYSCOMMAND,cmPaste,lParam); break;
case WM_KEYDOWN:
//
// Forward key messages to all targets
//
switch (wParam) { case VK_INSERT: if (GetKeyState(VK_SHIFT) & KEY_IS_DOWN) { PostToTargets(hwndList,WM_SYSCOMMAND,cmPaste,lParam); return (DefWindowProc(hwnd, message, wParam, lParam)); } break;
case VK_V: if (GetKeyState(VK_CONTROL) & KEY_IS_DOWN) { PostToTargets(hwndList,WM_SYSCOMMAND,cmPaste,lParam); return (DefWindowProc(hwnd, message, wParam, lParam)); } break;
}
case WM_KEYUP:
//
// Forward key messages to all targets
//
#ifndef TESTING
PostToTargets(hwndList, message, wParam, lParam); #endif // !TESTING
// drop through to default processing...
default: return(DefWindowProc(hwnd, message, wParam, lParam)); }
return 0; }
/****************************************************************************
FUNCTION: PostToTargets(HWND)
PURPOSE: Posts a message to all target windows
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/ BOOL PostToTargets( HWND hwndList, UINT message, WPARAM wparam, LPARAM lparam ) { INT TargetCount; INT Index; HWND hwndTarget; BOOL Restarted = FALSE;
RestartPost: TargetCount = (INT)SendMessage(hwndList, LB_GETCOUNT, 0, 0); if (TargetCount == LB_ERR) { return(FALSE); }
for (Index = 0; Index < TargetCount; Index ++) { hwndTarget = (HWND)SendMessage(hwndList, LB_GETITEMDATA, Index, 0); if ((hwndTarget != INVALID_HANDLE_VALUE) && !PostMessage(hwndTarget, message, wparam, lparam)) { if (Restarted) { return(FALSE); } if (!SelectGroupDefinition(GetCurrentGroup(), hwndList, TRUE)) { return(FALSE); } Restarted = TRUE; goto RestartPost; } }
return(TRUE); }
/****************************************************************************
FUNCTION: WindowListDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
****************************************************************************/
INT_PTR APIENTRY WindowListDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { INT NumberOfWindows = 0; INT counter = 0; HWND WindowHandleList[MAX_WINDOWS]; CHAR string[MAX_STRING_BYTES];
switch (message) {
case WM_INITDIALOG:
if (!WindowListDlgInit(hDlg)) { // Failed to initialize dialog, get out
EndDialog(hDlg, FALSE); }
return (TRUE);
case WM_COMMAND: switch (LOWORD(wParam)) {
case IDLB_WINDOWLIST: switch (HIWORD(wParam)) {
case LBN_DBLCLK: break; // drop through
default: return(0); }
// drop through on double click ...
case IDOK: NumberOfWindows = WindowListDlgEnd(hDlg, WindowHandleList);
if (NumberOfWindows > 0) { while ( counter++ < NumberOfWindows) {
//
// If the window is already in our list, don't add it
//
if (FindLBData(hwndList, (DWORD_PTR)WindowHandleList[counter - 1]) >= 0) { continue; }
//
// Don't add ourselves to the list
//
if (WindowHandleList[counter - 1] == GetParent(hDlg)) { continue; }
//
// Add the window to the list
//
if (GetWindowText(WindowHandleList[counter - 1], string, sizeof(string)) > 0) {
if (AddLBItemhwnd(hwndList, string, (LONG_PTR)WindowHandleList[counter - 1]) < 0) { } } } }
// We're done, drop through to enddialog...
case IDCANCEL:
EndDialog(hDlg, FALSE); return TRUE; break;
default: // We didn't process this message
return FALSE; break; } break;
default: // We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
DBG_UNREFERENCED_PARAMETER(lParam); }
/****************************************************************************
FUNCTION: WindowListDlgInit(HWND)
PURPOSE: Initialise the window list dialog
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/ BOOL WindowListDlgInit( HWND hDlg ) { // Fill the list box with top-level windows and their handles
EnumWindows(WindowListWindowEnum, (LONG_PTR)hDlg);
return(TRUE); }
/****************************************************************************
FUNCTION: WindowListWindowEnum
PURPOSE: Window enumeration call-back function. Adds each window to the window list-box
RETURNS: TRUE to continue enumeration, FALSE to stop.
****************************************************************************/ BOOL CALLBACK WindowListWindowEnum( HWND hwnd, LPARAM lParam ) { HWND hDlg = (HWND)lParam; CHAR string[MAX_STRING_BYTES];
//
// Don't add ourselves to the list
//
if (hwnd == hDlg) { return(TRUE); }
//
// Don't add our main window to the list
//
if (hwnd == hwndMain) { return(TRUE); }
if (GetWindowText(hwnd, string, MAX_STRING_BYTES) != 0) {
// This window has a caption, so add it to the list-box
AddLBItem(hDlg, IDLB_WINDOWLIST, string, (LONG_PTR)hwnd); }
return(TRUE); }
/****************************************************************************
FUNCTION: WindowListDlgEnd(HWND, *HWND)
PURPOSE: Cleans up after window list dialog
RETURNS: Number of window handles the user has selected or NULL
****************************************************************************/ INT WindowListDlgEnd( HWND hDlg, HWND *WindowList ) { HWND hwndListBox = GetDlgItem(hDlg, IDLB_WINDOWLIST); HWND hwndEdit; INT iItem, NumberOfItems; INT SelectedWindows[MAX_WINDOWS];
NumberOfItems = (INT)SendMessage(hwndListBox, LB_GETSELCOUNT, 0, 0);
if (SendMessage(hwndListBox, LB_GETSELITEMS, (WPARAM)NumberOfItems, (LPARAM)SelectedWindows) != NumberOfItems) { return 0; }
iItem = 0; while (iItem++ < NumberOfItems) { // Read selection from list-box and get its hwnd
WindowList[iItem-1] = (HWND)SendMessage(hwndListBox, LB_GETITEMDATA, SelectedWindows[iItem - 1], 0); } return (NumberOfItems); }
/****************************************************************************
FUNCTION: AboutDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for About dialog
****************************************************************************/
INT_PTR APIENTRY AboutDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) {
switch (message) {
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK:
// we're done, drop through to quit dialog....
case IDCANCEL: EndDialog(hDlg, TRUE); return TRUE; break;
default: // We didn't process this message
return FALSE; break; } break;
default: // We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
DBG_UNREFERENCED_PARAMETER(lParam); }
INT_PTR APIENTRY GroupAddDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { char szName[MAX_STRING_BYTES]; int item;
switch (msg) { case WM_INITDIALOG: GroupListInit(GetDlgItem(hDlg, IDCB_GROUPLIST), TRUE); SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, 0, 0); return(TRUE);
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (GetDlgItemText(hDlg, IDEF_GROUPNAME, szName, sizeof(szName)) > 0) { if (!AddGroupDefinition(szName, hwndList)) { EndDialog(hDlg, 0); } } else { MessageBeep(0); return(0); } EndDialog(hDlg, (INT_PTR)GetCurrentGroup()); return(0);
case IDCANCEL: EndDialog(hDlg, 0); return(0);
case IDCB_GROUPLIST: switch (HIWORD(wParam)) { case CBN_SELCHANGE: item = (int)SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETCURSEL, 0, 0); if (item != CB_ERR) { SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETLBTEXT, item, (LPARAM)szName); SetDlgItemText(hDlg, IDEF_GROUPNAME, szName); } return(0); } break; } } return(0); }
INT_PTR APIENTRY GroupDeleteDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { char szName[MAX_STRING_BYTES]; int item;
switch (msg) { case WM_INITDIALOG: GroupListInit(GetDlgItem(hDlg, IDCB_GROUPLIST), TRUE); SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, 0, 0); return(TRUE);
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if ((item = (int)SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETCURSEL, 0, 0)) != CB_ERR) { SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETLBTEXT, item, (LPARAM)szName); DeleteGroupDefinition(szName); } else { MessageBeep(0); return(0); } EndDialog(hDlg, (INT_PTR)szName); return(0);
case IDCANCEL: EndDialog(hDlg, 0); return(0); } } return(0); }
INT_PTR APIENTRY GroupSelectDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) { char szName[MAX_STRING_BYTES]; int item;
switch (msg) { case WM_INITDIALOG: GroupListInit(GetDlgItem(hDlg, IDCB_GROUPLIST), TRUE); if (GetCurrentGroup() != NULL) { item = (int)SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_FINDSTRING, -1, (LPARAM)(LPSTR)GetCurrentGroup()); SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, item, 0); } else { SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_SETCURSEL, 0, 0); } return(TRUE);
case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if ((item = (int)SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETCURSEL, 0, 0)) != CB_ERR) { SendDlgItemMessage(hDlg, IDCB_GROUPLIST, CB_GETLBTEXT, item, (LPARAM)szName); SelectGroupDefinition(szName, hwndList, FALSE); } else { MessageBeep(0); return(0); } EndDialog(hDlg, (INT_PTR)szName); return(0);
case IDCANCEL: EndDialog(hDlg, 0); return(0); } } return(0); }
|