/////////////////////////////////////////////////////////////// // win.cpp - simple window utility // // ver 1.0 builds generic windows with little effort // // // // Language: Visual C++, ver 6.0 // // Platform: Micron Dual Pentium Pro 200, WinNT 4.0 // // Application: CSE691 - Software Modeling and Analysis // // Author: Jim Fawcett, CST 2-187, Syracuse Univ. // // (315) 443-3948, fawcett@ecs.syr.edu // /////////////////////////////////////////////////////////////// #include #include #include #include #include #include "win.h" using namespace std; //----< initializing static data for class win >--------------- CRITICAL_SECTION win::_winSynch; // used for locking vector win::_winPtrs; // array of pointers to windows LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //----< win constructor takes the place of WinMain >----------- win::win(const string &title, int wd, int ht, int x, int y) : _title(title), _top(0), _left(10), _currY(_top) { // save pointer to window in static table // initialize critical section if this is the first window if(_winPtrs.size() == 0) InitializeCriticalSection(&_winSynch); lock(); _winPtrs.push_back(this); unlock(); // maxLines determines how many lines are saved by textBlock // sleepTime allows user to slow down display // using sleep() member function maxLines = 35; sleepTime = 0; // textBlock.clear(); HMODULE hInstance = GetModuleHandle(NULL); _ASSERT(hInstance != NULL); // // build window class structure WNDCLASSEX wndclass; static TCHAR szAppName[] = "winClass"; wndclass.cbSize = sizeof (wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); wndclass.lpszClassName = szAppName; wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION); // register window class ATOM val = RegisterClassEx (&wndclass); // create main window at specified location with specified size LPCTSTR text = TEXT(_title.c_str()); hwnd = CreateWindow (szAppName, text, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, x, y, wd, ht, NULL, NULL, hInstance, NULL); // display window GetClientRect(hwnd,&_rect); ShowWindow (hwnd, SW_SHOWNORMAL); UpdateWindow (hwnd); } //----< win destructor >--------------------------------------- win::~win() { // remove window pointer from static table vector::iterator it; lock(); it = find(_winPtrs.begin(),_winPtrs.end(),this); if(it != _winPtrs.end()) _winPtrs.erase(it); unlock(); // close the window and // delete critical section if this is the last window CloseHandle(hwnd); if(_winPtrs.size() == 0) DeleteCriticalSection(&_winSynch); } // //----< write text to window >--------------------------------- // // store text and its specified placement on screen // void win::putText(int x, int y, const std::string &str,BOOL erase) { dataItem di; di.text = str; di.x = x; di.y = y; fixedTextBlock.push_back(di); InvalidateRect(hwnd,NULL,erase); Sleep(20); } //----< write a series of lines to window >-------------------- // // store text only, will be placed by doPaint() // void win::putText(const std::string &str) { textBlock.push_back(str); if(textBlock.size() > maxLines) textBlock.pop_front(); InvalidateRect(hwnd,NULL,TRUE); Sleep(10); } //----< handle menu selections >------------------------------- // // - doesn't do anything except close window // int win::handleMenu(/*HWND hwnd*/WPARAM wParam) { HMENU hmenu; hmenu = GetMenu(hwnd); switch(LOWORD(wParam)) { case ID_FILE_EXIT : PostMessage(hwnd,WM_DESTROY,0,0); return 0; } return 0; } // //----< handle left mouse button down >------------------------ // // increase sleep time so display slows down // void win::doLeftButtonDown() { sleepTime += 100; InvalidateRect(hwnd,NULL,FALSE); } //----< handle rigth mouse button down >----------------------- // // clear text block and speed up window display // void win::doRightButtonDown() { textBlock.clear(); sleepTime=0; InvalidateRect(hwnd,NULL,FALSE); } //----< handle left mouse button up >-------------------------- void win::doLeftButtonUp() { InvalidateRect(hwnd,NULL,FALSE); } //----< handle rigth mouse button up >------------------------- void win::doRightButtonUp() { InvalidateRect(hwnd,NULL,FALSE); } // //----< compute mouse display string >------------------------- // // - construct a display string showing mouse coordinates // - invalidate a small rectangle around the string // - this is here only to show you how to use mouse coordinates // void win::doMouseDisplay(/*HWND hwnd*/POINT position) { RECT smallRect = { 10,10,100,25 }; int size; char display[100]; display[0] = '['; itoa(position.x,&display[1],10); size = strlen(display); display[size] = ','; itoa(position.y,&display[size+1],10); size = strlen(display); display[size] = ']'; display[size+1] = '\0'; _mouseDisplay = display; InvalidateRect(hwnd,&smallRect,TRUE); } //----< run message loop >------------------------------------- // // - called by a secondary thread, created with the window // - this allows the main thread to continue servicing the // console window // void win::run() { MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } } // //----< handle paint message >--------------------------------- // // called by windows any time screen needs updating, e.g., // when window covering changes, when client resizes, // when a button is clicked // void win::doPaint(RECT rect) { PAINTSTRUCT ps; // structure to hold paint info HDC hdc; // handle to device context hdc = BeginPaint (hwnd, &ps); // to minimize display flicker we are creating a device // context in memory, writing to that, then bliting // the memory context to the screen context at the end static HDC hdcMem = CreateCompatibleDC(hdc); RECT r; GetClientRect(hwnd,&r); int sWidth = r.right-r.left; int sHeight = r.bottom-r.top; static HBITMAP hBitmap; hBitmap = CreateCompatibleBitmap(hdcMem,sWidth,sHeight); SelectObject(hdcMem, hBitmap); SetTextColor(hdcMem, RGB(0,0,0)); SetBkColor (hdcMem, RGB(255,255,255)); SelectObject(hdcMem, GetStockObject (DEFAULT_GUI_FONT)); PatBlt(hdcMem,0,0,sWidth,sHeight,WHITENESS); if(textBlock.size() > 0) { // create a scrolling display that always shows the last // string written with putText(const string &s) and as // many predecessors as will fit on the screen TEXTMETRIC tm; // structure to hold font info GetTextMetrics (hdc, &tm); int height = r.bottom - r.top - _top; int numLines = height/tm.tmHeight; int start = textBlock.size() - numLines + 1; if(start < 0) start = 0; int y = _top + tm.tmHeight/2; int x = _left; int i; for(i=start; i 0) { int i; for(i=0; i---------------------------- unsigned int __stdcall thProc(void *pArgs) { // extract arguments thrdArg *pA = (thrdArg*)pArgs; // create window win currWin(pA->_title,pA->_ht,pA->_wd,pA->_x,pA->_y); // save pointer to window to return to main thread pA->_pWin = &currWin; // start window message loop currWin.run(); return 0; } //----< create window and start it running >------------------- win* win::create(const std::string &title, int width, int height, int x, int y) { // declare pointer to window to save value returned from thread function // and pack up parameters for thread function in structure win *pWin = NULL; thrdArg ta(title,width,height,x,y); // create thread to handle window unsigned int thID; HANDLE th = (HANDLE)_beginthreadex(NULL,0,thProc,&ta,0,&thID); // wait until window pointers have good addresses, set in thread proc while(!pWin) { pWin = ta._pWin; } return pWin; } // //----< process messages for main window >--------------------- LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { // retrieve pointer to window that sent this message, identified by hwnd // find in static table of windows pointers by comparing window handles win::lock(); win *pWin=win::_winPtrs[0]; int i; for(i=0; igetHandle()) { pWin = win::_winPtrs[i]; break; } win::unlock(); switch (iMsg) { case WM_CREATE : // define font for this window HDC hdc; // handle to device context win::lock(); hdc = GetDC (hwnd); SelectObject (hdc, GetStockObject (DEFAULT_GUI_FONT)); ReleaseDC (hwnd, hdc); win::unlock(); InvalidateRect(hwnd,NULL,TRUE); return 0; case WM_COMMAND : return pWin->handleMenu(wParam); case WM_SIZE : pWin->rect().right = LOWORD (lParam); pWin->rect().bottom = HIWORD (lParam); return 0; // case WM_LBUTTONDOWN : pWin->doLeftButtonDown(); return 0; case WM_RBUTTONDOWN : pWin->doRightButtonDown(); return 0; case WM_LBUTTONUP : pWin->doLeftButtonUp(); return 0; case WM_RBUTTONUP : pWin->doRightButtonUp(); return 0; case WM_MOUSEMOVE : pWin->point().x = LOWORD(lParam); pWin->point().y = HIWORD(lParam); pWin->doMouseDisplay(pWin->point()); return 0; case WM_PAINT : pWin->doPaint(pWin->rect()); return 0; case WM_DESTROY : PostQuitMessage (wParam); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); } // #ifdef TEST_WIN #include //----< test stub >-------------------------------------------- void main() { try { win *pWin1 = win::create("first win",300,200,40,40); int i; pWin1->setTopMargin(25); pWin1->setLeftMargin(25); pWin1->setMaxLines(20); pWin1->putText( pWin1->getLeftMargin()-15,8,"This is a display header line" ); for(i=0; i<1000; i++) { ostringstream temp; temp << " -------- this is text line number" << std::setw(4) << i << " --------"; pWin1->putText(temp.str()); cout << "\n putting stuff in first win"; pWin1->sleep(); } win *pWin2 = win::create("second win",300,200,400,300); string sArray[3] = { "first string", "second string", "third string" }; for(i=0; i<3; i++) { pWin2->putText(10+10*i,10+15*i,sArray[i],FALSE); cout << "\n putting stuff in second win"; } } catch(...) { cout << "\n\n program aborted - " << "attempt to write to window after closing"; } cout << "\n\n press any key to continue "; char ch; cin.read(&ch,1); cout << "\n"; } #endif