00001
00005
00006
00038 #include "stdafx.h"
00039 #include "resource.h"
00040
00041
00042 #include "BitmapScreen.h"
00043 #include "MousePipe.h"
00044 #include "ScreenPipe.h"
00045 #include "UpdateHandler.h"
00046
00047 #define DEFAULTNAME TEXT("Client")
00048 #define DEFAULTCAPTURE TEXT("ScreenCap_")
00049
00050
00051 HINSTANCE hInst;
00052 CHString titleBarText;
00053 CHString windowClass;
00054
00055 BitmapScreen *virtualScreen;
00056 UpdateHandler *updater = NULL;
00057
00058 MousePipe *mouseServer = NULL;
00059 ScreenPipe *screenServer = NULL;
00060
00061 DIBitmap mainBkGnd;
00062
00063 TString clientName( DEFAULTNAME );
00064
00065 TString captureName( DEFAULTCAPTURE );
00066 int captureFrequency = 1;
00067 int captureLimit = 0;
00068 bool doCapture = false;
00069
00070
00071 ATOM MyRegisterClass(HINSTANCE hInstance);
00072 BOOL InitInstance(HINSTANCE, int);
00073 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
00074 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
00075 LRESULT CALLBACK Name(HWND, UINT, WPARAM, LPARAM);
00076 LRESULT CALLBACK Connect(HWND, UINT, WPARAM, LPARAM);
00077 LRESULT CALLBACK Options(HWND, UINT, WPARAM, LPARAM);
00078
00082 int APIENTRY wWinMain(HINSTANCE hInstance,
00083 HINSTANCE hPrevInstance,
00084 PWSTR lpCmdLine,
00085 int nCmdShow)
00086 {
00087 chWindows9xNotAllowed();
00088
00089 MSG msg;
00090 HACCEL hAccelTable;
00091
00092
00093 titleBarText.LoadString(IDS_APP_TITLE);
00094 windowClass.LoadString(IDC_WINDRESSING);
00095
00096
00097
00098 MyRegisterClass(hInstance);
00099
00100 if (!InitInstance (hInstance, nCmdShow)) {
00101 return false;
00102 }
00103
00104 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WINDRESSING);
00105
00106
00107 while (GetMessage(&msg, NULL, 0, 0)) {
00108 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
00109 TranslateMessage(&msg);
00110 DispatchMessage(&msg);
00111 }
00112 }
00113
00114 return msg.wParam;
00115 }
00116
00117
00119 ATOM MyRegisterClass(HINSTANCE hInstance)
00120 {
00121 WNDCLASSEX wcex;
00122
00123 wcex.cbSize = sizeof(WNDCLASSEX);
00124
00125 wcex.style = CS_HREDRAW | CS_VREDRAW;
00126 wcex.lpfnWndProc = (WNDPROC)WndProc;
00127 wcex.cbClsExtra = 0;
00128 wcex.cbWndExtra = 0;
00129 wcex.hInstance = hInstance;
00130 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_WINDRESSING);
00131 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
00132 wcex.hbrBackground = NULL;
00133 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDRESSING);
00134 wcex.lpszClassName = windowClass;
00135 wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
00136
00137 return RegisterClassEx(&wcex);
00138 }
00139
00141 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
00142 {
00143 HWND hWnd;
00144
00145 hInst = hInstance;
00146
00147 hWnd = CreateWindowEx(
00148 0,
00149 windowClass,
00150 (LPCWSTR)titleBarText + TString(TEXT(" - Disconnected")),
00151 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
00152 CW_USEDEFAULT,
00153 0,
00154 CW_USEDEFAULT,
00155 0,
00156 NULL,
00157 NULL,
00158 hInstance,
00159 NULL);
00160
00161 if (!hWnd)
00162 {
00163 return false;
00164 }
00165
00166 ShowWindow(hWnd, nCmdShow);
00167
00168 return true;
00169 }
00170
00172
00174
00176
00177
00183 bool registerMouse(bool down)
00184 {
00185 static bool downLastSeen = false;
00186
00187 if( down ){
00188 if ( !downLastSeen ){
00189 if( !mouseServer->queueMessage(virtualScreen->getScreenX(), virtualScreen->getScreenY(), 0) )
00190 return false;
00191 } else {
00192 if( !mouseServer->queueMessage(virtualScreen->getScreenX(), virtualScreen->getScreenY(), 1))
00193 return false;
00194 downLastSeen = false;
00195
00196 if( !mouseServer->queueMessage(virtualScreen->getScreenX(), virtualScreen->getScreenY(), 0))
00197 return false;
00198 }
00199 } else {
00200 if ( downLastSeen ){
00201 if( !mouseServer->queueMessage(virtualScreen->getScreenX(), virtualScreen->getScreenY(), 1))
00202 return false;
00203 } else {
00204 mouseServer->queueMessage(virtualScreen->getScreenX(), virtualScreen->getScreenY(), 0);
00205 downLastSeen = true;
00206
00207 if( !mouseServer->queueMessage(virtualScreen->getScreenX(), virtualScreen->getScreenY(), 1))
00208 return false;
00209
00210 }
00211 }
00212
00213 downLastSeen = down;
00214 return true;
00215 }
00216
00222 void Cls_OnLButtonUp(HWND hWnd, int x, int y, UINT)
00223 {
00224 if( mouseServer == NULL )
00225 return;
00226
00227 if( !downOnScreen )
00228 return;
00229
00230 virtualScreen->PointOnScreen(x,y);
00231
00232 int command = IDRETRY;
00233
00234 while( !registerMouse(false) && command == IDRETRY ){
00235 if( !mouseServer->isConnected() )
00236 return;
00237
00238 command = MessageBox(hWnd,
00239 TEXT("VCC has too many mouse messages or \nis no longer connected.\n\nPress Cancel to disconnect."),
00240 TEXT("Couldn't Queue Message"),
00241 MB_RETRYCANCEL | MB_ICONWARNING | MB_APPLMODAL);
00242
00243 if( command == IDCANCEL ){
00244 SendNotifyMessage(hWnd, WM_COMMAND, IDM_DISCONNECT, 0);
00245 }
00246 }
00247 downOnScreen = false;
00248 }
00249
00256 void Cls_OnLButtonDown(HWND hWnd, BOOL, int x, int y, UINT)
00257 {
00258 if( mouseServer == NULL )
00259 return;
00260
00261 if( !virtualScreen->PointOnScreen(x,y) )
00262 return;
00263
00264 if( registerMouse(true) ){
00265 downOnScreen = true;
00266 } else {
00267 if( !mouseServer->isConnected() )
00268 return;
00269
00270 if( IDCANCEL == MessageBox(hWnd,
00271 TEXT("VCC has too many mouse messages or \nis no longer connected.\n\nPress Cancel to disconnect."),
00272 TEXT("Couldn't Queue Message"),
00273 MB_OKCANCEL | MB_ICONWARNING | MB_APPLMODAL) ){
00274
00275 SendNotifyMessage(hWnd, WM_COMMAND, IDM_DISCONNECT, 0);
00276 }
00277
00278 }
00279 }
00280
00282
00284
00286
00287 bool Cls_OnEraseBkgnd(HWND hWnd, HDC hDC)
00288 {
00289 SetDIBitsToDevice(
00290 hDC,
00291 0, 0,
00292 mainBkGnd.getPBITMAPINFOHEADER()->biWidth,
00293 abs(mainBkGnd.getPBITMAPINFOHEADER()->biHeight),
00294 0, 0,
00295 0,
00296 abs(mainBkGnd.getPBITMAPINFOHEADER()->biHeight),
00297 mainBkGnd.getPBytes(),
00298 mainBkGnd.getPBITMAPINFO(),
00299 DIB_RGB_COLORS);
00300 return true;
00301 }
00302
00304
00306 void Cls_OnPaint(HWND hWnd)
00307 {
00308 PAINTSTRUCT ps;
00309 HDC hDC = BeginPaint(hWnd, &ps);
00310
00311 virtualScreen->paint(hDC);
00312
00313 EndPaint(hWnd, &ps);
00314 }
00315
00317
00319
00320 bool Cls_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
00321 {
00322 if( !mainBkGnd.loadFile(TEXT("pigi.bmp")) ){
00323 MessageBox(hWnd,
00324 TEXT("Press any key to continue, or any other to quit.\n"),
00325 TEXT("Error - Can't find background image \"pigi.bmp\""),
00326 MB_OK | MB_ICONERROR | MB_APPLMODAL);
00327 return false;
00328 }
00329
00330 RECT clientArea, windowArea;
00331
00332 GetClientRect(hWnd, &clientArea);
00333 GetWindowRect(hWnd, &windowArea);
00334
00335 SetWindowPos(
00336 hWnd,
00337 HWND_TOP,
00338 0, 0,
00339 windowArea.right - windowArea.left
00340 + mainBkGnd.getPBITMAPINFOHEADER()->biWidth
00341 - clientArea.right,
00342 windowArea.bottom - windowArea.top
00343 + mainBkGnd.getPBITMAPINFOHEADER()->biHeight
00344 - clientArea.bottom,
00345 SWP_NOMOVE);
00346
00347 virtualScreen = new BitmapScreen(114, 139, 240, -320);
00348
00349
00350 DIBitmap *initial = virtualScreen->getWriteBuffer();
00351 if( !initial->loadFile( TEXT("initial.bmp") ) ){
00352 virtualScreen->DoneWriting();
00353 } else {
00354 virtualScreen->DoneWriting();
00355
00356 initial = virtualScreen->getWriteBuffer();
00357 *initial = *virtualScreen->getReadBuffer();
00358
00359
00360
00361
00362
00363 virtualScreen->DoneReading();
00364 virtualScreen->DoneWriting();
00365 }
00366
00367 UpdateWindow(hWnd);
00368
00369 return true;
00370 }
00371
00373 void Cls_OnDestroy(HWND)
00374 {
00375 PostQuitMessage(0);
00376 }
00377
00379 void Cls_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
00380 {
00381 static int capNo = 0;
00382 const DIBitmap* capture;
00383
00384
00385 switch (id){
00386 case IDM_ABOUT:
00387 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
00388 break;
00389 case IDM_SC_OPTIONS:
00390 if( IDOK == DialogBox(hInst, (LPCTSTR)IDD_OPTIONS, hWnd, (DLGPROC)Options) ){
00391 ModifyMenu(GetMenu(hWnd), IDM_SC_ACTIVATE, MF_BYCOMMAND | MF_CHECKED,
00392 IDM_SC_ACTIVATE, TEXT("Auto Capture"));
00393 doCapture = true;
00394 if( updater != NULL )
00395 updater->enableCapture();
00396 }
00397 break;
00398 case IDM_SC_CAPTURE:
00399 capture = virtualScreen->getReadBuffer();
00400 capture->saveFile(TString(TEXT("capture")) + TString(capNo++) + TString(TEXT(".bmp")));
00401 virtualScreen->DoneReading();
00402 break;
00403 case IDM_SC_ACTIVATE:
00404 if( !doCapture ){
00405 ModifyMenu(GetMenu(hWnd), IDM_SC_ACTIVATE, MF_BYCOMMAND | MF_CHECKED,
00406 IDM_SC_ACTIVATE, TEXT("Auto Capture"));
00407 doCapture = true;
00408 if( updater != NULL )
00409 updater->enableCapture();
00410 } else {
00411 ModifyMenu(GetMenu(hWnd), IDM_SC_ACTIVATE, MF_BYCOMMAND | MF_UNCHECKED,
00412 IDM_SC_ACTIVATE, TEXT("Auto Capture"));
00413 doCapture = false;
00414 if( updater != NULL )
00415 updater->disableCapture();
00416 }
00417 break;
00418 case IDM_DISCONNECT:
00419 SetWindowText( hWnd, (LPCWSTR)titleBarText
00420 + TString(TEXT(" - Disconnected")) );
00421
00422 EnableMenuItem(
00423 GetMenu(hWnd),
00424 IDM_DISCONNECT,
00425 MF_GRAYED);
00426 EnableMenuItem(
00427 GetMenu(hWnd),
00428 IDM_CONNECT,
00429 MF_ENABLED);
00430 EnableMenuItem(
00431 GetMenu(hWnd),
00432 IDM_SC_OPTIONS,
00433 MF_ENABLED);
00434
00435
00436 updater->stop(false);
00437
00438 delete updater;
00439 updater = NULL;
00440
00441 delete mouseServer;
00442 mouseServer = NULL;
00443 delete screenServer;
00444 screenServer = NULL;
00445
00446 break;
00447 case IDM_CONNECT:
00448 if( DialogBox(hInst, (LPCTSTR)IDD_NAME, hWnd, (DLGPROC)Name) == IDOK ){
00449 SetWindowText( hWnd, (LPCWSTR)titleBarText
00450 + TString(TEXT(" - ")) + clientName + TString(TEXT(" - Connecting...")) );
00451
00452 if( DialogBox(hInst, (LPCTSTR)IDD_CONNECT, hWnd, (DLGPROC)Connect) == IDOK ){
00453 SetWindowText( hWnd, (LPCWSTR)titleBarText
00454 + TString(TEXT(" - ")) + clientName + TString(TEXT(" - Connected")) );
00455
00456 EnableMenuItem(
00457 GetMenu(hWnd),
00458 IDM_CONNECT,
00459 MF_GRAYED);
00460 EnableMenuItem(
00461 GetMenu(hWnd),
00462 IDM_DISCONNECT,
00463 MF_ENABLED);
00464 EnableMenuItem(
00465 GetMenu(hWnd),
00466 IDM_SC_OPTIONS,
00467 MF_GRAYED);
00468
00469 updater = new UpdateHandler(*screenServer, *virtualScreen, hWnd);
00470 if( doCapture ){
00471 updater->setCaptureName(captureName);
00472 updater->setCaptureFrequency(captureFrequency);
00473 updater->setCaptureLimit(captureLimit);
00474 updater->enableCapture();
00475 }
00476 assert( updater->run() );
00477 } else {
00478 SetWindowText( hWnd, (LPCWSTR)titleBarText
00479 + TString(TEXT(" - Disconnected")) );
00480 }
00481 }
00482 break;
00483 case IDM_EXIT:
00484 DestroyWindow(hWnd);
00485 break;
00486 default:
00487 FORWARD_WM_COMMAND(hWnd, id, hWndCtl, codeNotify, DefWindowProc);
00488 }
00489 }
00490
00492
00494
00496 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
00497 {
00498 switch (message) {
00499 HANDLE_MSG(hWnd, WM_CREATE, Cls_OnCreate);
00500 HANDLE_MSG(hWnd, WM_COMMAND, Cls_OnCommand);
00501 HANDLE_MSG(hWnd, WM_LBUTTONDOWN, Cls_OnLButtonDown);
00502 HANDLE_MSG(hWnd, WM_LBUTTONUP, Cls_OnLButtonUp);
00503 HANDLE_MSG(hWnd, WM_ERASEBKGND, Cls_OnEraseBkgnd);
00504 HANDLE_MSG(hWnd, WM_PAINT, Cls_OnPaint);
00505 HANDLE_MSG(hWnd, WM_DESTROY, Cls_OnDestroy);
00506 default:
00507 return DefWindowProc(hWnd, message, wParam, lParam);
00508 }
00509 }
00510
00512 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
00513 {
00514 switch (message){
00515 case WM_INITDIALOG:
00516 return true;
00517 case WM_COMMAND:
00518 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
00519 EndDialog(hDlg, LOWORD(wParam));
00520 return true;
00521 }
00522 break;
00523 }
00524 return false;
00525 }
00526
00528 LRESULT CALLBACK Options(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
00529 {
00530 TCHAR temp[200];
00531 int tempInt;
00532
00533 switch (message){
00534 case WM_INITDIALOG:
00535 SetDlgItemText(hDlg, IDC_FILENAME, captureName );
00536 SetDlgItemText(hDlg, IDC_FREQUENCY_VALUE, TString(captureFrequency));
00537 if( captureLimit != 0 ){
00538 SetDlgItemText(hDlg, IDC_LIMIT_VALUE, TString(captureLimit));
00539 CheckDlgButton(hDlg, IDC_LIMIT_CHECK, BST_CHECKED);
00540 } else {
00541 SetDlgItemText(hDlg, IDC_LIMIT_VALUE, TEXT(""));
00542 CheckDlgButton(hDlg, IDC_LIMIT_CHECK, BST_UNCHECKED);
00543 }
00544
00545 return true;
00546 case WM_COMMAND:
00547 switch(wParam){
00548 case IDOK:
00549 case IDAPPLY:
00550 GetDlgItemText(hDlg, IDC_FILENAME, temp, 200);
00551 captureName = temp;
00552
00553 GetDlgItemText(hDlg, IDC_FREQUENCY_VALUE, temp, 200);
00554 swscanf(temp, L"%d", &tempInt);
00555 if( tempInt > 0 )
00556 captureFrequency = tempInt;
00557
00558 if( BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_LIMIT_CHECK) ){
00559 GetDlgItemText(hDlg, IDC_LIMIT_VALUE, temp, 200);
00560 swscanf(temp, L"%d", &tempInt);
00561 if( tempInt > 0 ){
00562 captureLimit = tempInt;
00563 } else {
00564 captureLimit = 0;
00565 }
00566 }
00567 if( wParam == IDAPPLY){
00568 SetDlgItemText(hDlg, IDC_FILENAME, captureName );
00569 SetDlgItemText(hDlg, IDC_FREQUENCY_VALUE, TString(captureFrequency));
00570 if( captureLimit != 0 ){
00571 SetDlgItemText(hDlg, IDC_LIMIT_VALUE, TString(captureLimit));
00572 CheckDlgButton(hDlg, IDC_LIMIT_CHECK, BST_CHECKED);
00573 } else {
00574 SetDlgItemText(hDlg, IDC_LIMIT_VALUE, TEXT(""));
00575 CheckDlgButton(hDlg, IDC_LIMIT_CHECK, BST_UNCHECKED);
00576 }
00577 return true;
00578 }
00579 case IDCANCEL:
00580 EndDialog(hDlg, LOWORD(wParam));
00581 return true;
00582 }
00583 break;
00584 }
00585 return false;
00586 }
00587
00589 LRESULT CALLBACK Name(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
00590 {
00591 TCHAR temp[241];
00592
00593 switch (message){
00594 case WM_INITDIALOG:
00595 SetDlgItemText(hDlg, IDC_CLIENT_NAME, clientName );
00596 return true;
00597 case WM_COMMAND:
00598 switch(wParam){
00599 case IDOK:
00600 GetDlgItemText(hDlg, IDC_CLIENT_NAME, temp, 240);
00601 clientName = temp;
00602 case IDCANCEL:
00603 EndDialog(hDlg, LOWORD(wParam));
00604 return true;
00605 }
00606 break;
00607 }
00608 return false;
00609 }
00610
00612 VOID WINAPI waitForMouse(PVOID param, bool)
00613 {
00614 HWND hDlg = (HWND) param;
00615
00616 CheckDlgButton(hDlg, IDC_MOUSE_OUT, BST_CHECKED);
00617
00618 SendNotifyMessage(hDlg, WM_COMMAND, IDOK, 1);
00619 }
00620
00622 VOID WINAPI waitForScreen(PVOID param, bool)
00623 {
00624 HWND hDlg = (HWND) param;
00625
00626 CheckDlgButton(hDlg, IDC_SCRNBUFF_IN, BST_CHECKED);
00627
00628 SendNotifyMessage(hDlg, WM_COMMAND, IDOK, 2);
00629 }
00630
00631
00632
00633 WaitCallback* mouseWait;
00634 WaitCallback* screenWait;
00635
00637 LRESULT CALLBACK Connect(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
00638 {
00639 switch (message){
00640 case WM_INITDIALOG:
00641 mouseServer = new MousePipe( clientName );
00642 screenServer = new ScreenPipe( clientName );
00643
00644 if( !(mouseServer->serve() && screenServer->serve()) ){
00645 delete mouseServer;
00646 mouseServer = NULL;
00647 delete screenServer;
00648 screenServer = NULL;
00649
00650 MessageBox(
00651 hDlg,
00652 TEXT("Failed to serve pipes.\nCheck for another client with the same name.\n"),
00653 TEXT("Can't connect"),
00654 MB_OK);
00655 EndDialog(hDlg, LOWORD(wParam));
00656 return true;
00657 }
00658
00659 mouseWait = new WaitCallback;
00660 screenWait = new WaitCallback;
00661
00662 assert(mouseWait->registerWaitForSingleObject(
00663 mouseServer->getConnectedEventHandle(),
00664 &waitForMouse,
00665 hDlg,
00666 INFINITE,
00667 true));
00668
00669 assert(screenWait->registerWaitForSingleObject(
00670 screenServer->getConnectedEventHandle(),
00671 &waitForScreen,
00672 hDlg,
00673 INFINITE,
00674 true));
00675
00676 return true;
00677 break;
00678 case WM_COMMAND:
00679 switch(wParam){
00680 case IDCANCEL:
00681 mouseWait->unregisterWait();
00682 screenWait->unregisterWait();
00683 delete mouseWait;
00684 delete screenWait;
00685
00686 delete mouseServer;
00687 mouseServer = NULL;
00688 delete screenServer;
00689 screenServer = NULL;
00690 case IDOK:
00691 switch(lParam){
00692 case 2:
00693 screenWait->unregisterWait();
00694 delete screenWait;
00695 screenWait = NULL;
00696 if( mouseWait != NULL )
00697 return true;
00698 break;
00699 case 1:
00700 mouseWait->unregisterWait();
00701 delete mouseWait;
00702 mouseWait = NULL;
00703 if( screenWait != NULL )
00704 return true;
00705 break;
00706 default:
00707 break;
00708 }
00709 EndDialog(hDlg, LOWORD(wParam));
00710 return true;
00711 }
00712 break;
00713 }
00714 return false;
00715 }