void LampGroup::GenerateBinary(BYTE *&pByte, INT &length) { length = 8*m_Lamps.size(); pByte = new BYTE[length]; bzero(pByte, length); INT offset = 0; //记录当前路灯数据的偏移 SHORT *pShort = ZTNULL; list<Lamp*>::const_iterator it = m_Lamps.begin(); while (it != m_Lamps.end()) { BYTE *pLampByte = ZTNULL; INT len = 0; (*it)->GenerateBinary(pLampByte, len); memcpy(pByte+offset, pLampByte, len); pShort = (SHORT *)(pByte+offset+6); *pShort = MAKESHORT(m_State, m_Lddout); delete pLampByte; offset += 8; it++; } }
VOID sendCharToWnd( HANCHAR hch ) { if( ISHCH( hch )) { hch = hch_sy2ks( hch ); hch = MAKESHORT( HIBYTE( hch ), LOBYTE( hch )); } WinPostMsg( hwndCurrentInput, WM_CHAR, MPFROMSH2CH( KC_CHAR, 1, 0 ), MPFROM2SHORT( hch, 0 )); }
MRESULT EXPENTRY WndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) { // static POINTS DragStartPtrPos; POINTL ptl; static char Row, Col; static BOOL HasMoved = FALSE; static BOOL IntroSoundPlayed = FALSE; static BOOL RealPaint = TRUE; // indicates whether the board // has to be repainted or just copied INT aktscan; CHAR msgtext[256]; ULONG ulResponse; // ERRORID errId; switch( msg ){ case WM_CREATE: if( !InfoData.LoadHigh() ){ // get previously saved highscores InfoData.ResetHigh(); WinMessageBox( HWND_DESKTOP, hwndMain, "The file scores.dat " \ "(which is in the current directory) was somehow corrupted." \ " All Highscores will be reset to Zero.", "Error when loading Highscores", 0, MB_OK | MB_INFORMATION ); } // allocate memory for global variables; see GLOBALS struct in tgraph.h pg = new GLOBALS; // initialize globals to zero memset( pg, 0, sizeof( GLOBALS )); // store globals pointer into client window words; see WinRegisterClass // WinSetWindowULong( hwnd, QWL_USER, (ULONG) pg ); wcprintf("1: %x", WinGetLastError( hab ) ); DosCreateEventSem( NULL, &hevWaitAfterScan, 0, FALSE ); // Sem is created in reset state DosCreateEventSem( NULL, &hevHiScoreWin, 0, FALSE ); DosCreateEventSem( NULL, &hevWaitAfterSound, 0, FALSE ); DosCreateEventSem( NULL, &hevWaitSoundReady, 0, TRUE ); // Sem is created in posted state // hevWaitAfterScan and hewWaitAfterSound are used to indicate // when the respective WM_CREATE routines are done. // after that they are in posted state, as desired // initialize globals with important data pg->hab = hab; pg->hwndClient = hwnd; pg->hwndFrame = WinQueryWindow( hwnd, QW_PARENT ); pg->hwndTitlebar = WinWindowFromID( pg->hwndFrame, FID_TITLEBAR ); pg->hwndMenubar = WinWindowFromID( pg->hwndFrame, FID_MENU ); // create graphics and sound threads pg->tidTSound = _beginthread( &threadsound, NULL, LEN_STACK, NULL ); pg->tidTGraph = _beginthread( &threadgraph, NULL, LEN_STACK, NULL ); DosWaitEventSem( hevWaitAfterSound, SEM_INDEFINITE_WAIT ); WinPostMsg( pg->hwndTSound, WM_SOUND_INTRO, MPFROMHWND(hwnd), 0 ); // wait for the sound's WM_CREATE DosWaitEventSem( hevWaitAfterScan, SEM_INDEFINITE_WAIT ); // wait for the graphics' WM_CREATE InfoData.ShipsNotFound = GBoard.GetShipNumber(); wcprintf("create: %x", WinGetLastError( hab ) ); return (MRESULT)0; case WM_CONTROL: break; case WM_QUIT: break; case WM_CLOSE: // this message is sent before WM_QUIT InfoData.SaveHigh( WinGetCurrentTime(hab) ); // save the highscores and provide a random seed // get pointer to globals from window words // pg = (PGLOBALS) WinQueryWindowULong( hwnd, QWL_USER ); // tell object windows to quit, then exit their threads // WinSendMsg( pg->hwndTGraph, WM_DESTROY, mp1, mp2 ); WinPostMsg( pg->hwndTGraph, WM_QUIT, mp1, mp2 ); // WinSendMsg( pg->hwndTSound, WM_DESTROY, mp1, mp2 ); WinPostMsg( pg->hwndTSound, WM_QUIT, mp1, mp2 ); DosCloseEventSem( hevWaitAfterScan ); DosCloseEventSem( hevHiScoreWin ); DosCloseEventSem( hevWaitAfterSound ); DosCloseEventSem( hevWaitSoundReady ); WriteProfile( hab ); delete pg; return (MRESULT) 0; case WM_ERASEBACKGROUND: wcprintf("erasebackground"); // return (MRESULT) FALSE; return (MRESULT) TRUE; case WM_PAINT: /////////////////////////////////// { RECTL rectl; WinQueryWindowRect( pg->hwndClient, &rectl ); wcprintf("Linienrechteck: Breite: %d H”he: %d", rectl.xRight, rectl.yTop ); // test size: GpiSetColor( hpsGlob, CLR_RED ); ptl.x = rectl.xLeft; ptl.y = rectl.yBottom; GpiMove( hpsGlob, &ptl ); ptl.x = rectl.xRight; ptl.y = rectl.yTop; GpiLine( hpsGlob, &ptl ); } /////////////////////////// break; case WM_SIZE: wcprintf("main wnd function wm-size"); RealPaint = TRUE; GBoard.SetPMBoardValues( SHORT1FROMMP( mp2 ), SHORT2FROMMP( mp2 ) ); WndResize( hwnd ); wcprintf("size: %x", WinGetLastError( hab ) ); break; case WM_BEGINDRAG: WinSetCapture( HWND_DESKTOP, hwnd ); // capture the mouse pointer GBoard.SetfDrag( TRUE ); // indicate that mouse is being dragged GBoard.ResetFirstDraw(); // for initialization of drag op. fHideSquare = TRUE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( 0, 0 ) ); // GBoard.ShowPointerPos( hwnd, 0, 0 ); // removes the square ptl.x = SHORT1FROMMP(mp1); ptl.y = SHORT2FROMMP(mp1); Row = GBoard.GetBoardRow( ptl.y ); // starting point of drag Col = GBoard.GetBoardCol( ptl.x ); // operation; static! return (MRESULT)TRUE; case WM_MOUSEMOVE: if( GBoard.GetfDrag() ){ // if mouse is being dragged WinSendMsg( pg->hwndTGraph, WM_DRAWDRAGLINE, mp1, MPFROM2SHORT( Row, Col ) ); HasMoved = TRUE; } else { // mouse is moved normally if( !fHideSquare ) WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), mp1 ); // GBoard.ShowPointerPos( hwnd, SHORT1FROMMP(mp1), // SHORT2FROMMP(mp1)); } break; case WM_ENDDRAG: WinSetCapture( HWND_DESKTOP, NULLHANDLE ); // release the captured // mouse pointer if( HasMoved ){ // mousemove has actually been moved WinSendMsg( pg->hwndTGraph, WM_MARKDRAGLINE, MPFROM2SHORT( Row, Col ), 0 ); HasMoved = FALSE; } GBoard.SetfDrag( FALSE ); GBoard.ClearDrawPoint(); // because no square is drawn right now fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), mp1 ); // GBoard.ShowPointerPos( hwnd, SHORT1FROMMP(mp1), SHORT2FROMMP(mp1)); // draws square at the current ptr pos break; case WM_CHAR: // key was pressed if( SHORT2FROMMP( mp2 ) != VK_SPACE ) break; // only space is interesting if( GBoard.GetfDrag() ) break; // do nothing while dragging if( !GBoard.GetfShowLines() ){ // lines not visible yet GBoard.SetfShowLines( TRUE ); WinSendMsg( pg->hwndTGraph, WM_DISPLAYLINES, 0, 0 ); } break; case WM_BUTTON1CLICK: if( !InfoData.ShipsNotFound ) break; // game is finished ptl.x = (LONG)SHORT1FROMMP( mp1 ); ptl.y = (LONG)SHORT2FROMMP( mp1 ); Row = GBoard.GetBoardRow( ptl.y ); Col = GBoard.GetBoardCol( ptl.x ); if( !Row || !Col ) break; fHideSquare = TRUE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( 0, 0 ) ); // GBoard.ShowPointerPos( hwnd, 0, 0 ); // hides pointer square if(( aktscan = GBoard.GetDiscovered( Row, Col )) != -1 ){ WinSendMsg( pg->hwndTGraph, WM_DRAWPMPLACE, MPFROMHWND(hwnd), MPFROMSH2CH( MAKESHORT(Row, Col), (CHAR)aktscan,(CHAR)TRUE)); // umstricken auf WinPostMsg // toggle Place display } else { // scan Place DosResetEventSem( hevWaitAfterScan, &ulResponse ); // DosBeep(500, 150 ); WinPostMsg( pg->hwndTGraph, WM_GRAPH_SCAN, MPFROMHWND(hwnd), MPFROM2SHORT( Row, Col ) ); // DosBeep( 800, 150 ); WinWaitEventSem( hevWaitAfterScan, SEM_INDEFINITE_WAIT ); // DosBeep( 1000, 150 ); // first the scanning sounds must be played (and finished) aktscan = GBoard.Scan( Row, Col ); if( aktscan == GBoard.GetShipNumber() + 10 ){ InfoData.ShipsNotFound--; WinPostMsg( pg->hwndTSound, WM_SOUND_FOUNDSHIP, MPFROMHWND(hwnd), 0 ); } else { if( aktscan ) WinPostMsg( pg->hwndTSound, WM_SOUND_FOUND, MPFROMHWND(hwnd), MPFROMLONG( aktscan ) ); else WinPostMsg( pg->hwndTSound, WM_SOUND_FOUND0, MPFROMHWND(hwnd), 0 ); } WinWaitEventSem( hevWaitAfterScan, SEM_INDEFINITE_WAIT ); // waits until scanning is done, and only then displays the // field icon // hps = WinGetPS( hwnd ); WinSendMsg( pg->hwndTGraph, WM_DRAWPMPLACE, MPFROMHWND(hwnd), MPFROMSH2CH( MAKESHORT(Row, Col), (CHAR)aktscan,(CHAR)TRUE)); // umstricken auf WinPostMsg WinPostMsg( pg->hwndTGraph, WM_SHOWSTATUSLINE, 0, 0 ); // ShowStatusLine( hps, GBoard.MovesNeeded(), InfoData.ShipsNotFound, // GBoard.GetWinWidth(), GBoard.GetWinHeight() ); // WinReleasePS( hps ); if( !InfoData.ShipsNotFound ){ // game is finished, all ships found Score = GBoard.MovesNeeded(); if ( !InfoData.ReturnLastHigh() // still space in the hiscore table || Score < InfoData.ReturnLastHigh() ){ // player kicks last one out // player enters highscore table WinPostMsg( pg->hwndTSound, WM_SOUND_NEWHISCORE, MPFROMHWND(hwnd), 0 ); WinWaitEventSem( hevHiScoreWin, SEM_INDEFINITE_WAIT ); // waits until the NEWHISCORE sound is actually played WinDlgBox( HWND_DESKTOP, hwnd, HighScoreDlgProc, (HMODULE)0, IDR_HIGHSCOREDLG, NULL ); WinPostMsg( hwnd, WM_COMMAND, MPFROMSHORT(IDM_GAMEHIGH), (MPARAM)0 ); // show highscore-table DosResetEventSem( hevHiScoreWin, &ulResponse ); // resets the sem again } else { WinPostMsg( pg->hwndTSound, WM_SOUND_LOST, MPFROMHWND(hwnd), 0 ); WinWaitEventSem( hevHiScoreWin, SEM_INDEFINITE_WAIT ); // waits until the NEWHISCORE sound is actually played sprintf( msgtext, "You needed %d moves to find the lost ships. " \ "To enter the highscore list you need %d moves." \ " So try again!", Score, InfoData.ReturnLastHigh() - 1 ); WinMessageBox( HWND_DESKTOP, hwnd, msgtext, "Oh, Shit!", 0, MB_OK | MB_INFORMATION | MB_HELP ); } } } fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( ptl.x, ptl.y ) ); // GBoard.ShowPointerPos( hwnd, ptl.x, ptl.y ); // redisplay ptr square break; case WM_BUTTON2CLICK: fHideSquare = TRUE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( 0, 0 ) ); ptl.x = (LONG)SHORT1FROMMP( mp1 ); ptl.y = (LONG)SHORT2FROMMP( mp1 ); Row = GBoard.GetBoardRow( ptl.y ); Col = GBoard.GetBoardCol( ptl.x ); WinSendMsg( pg->hwndTGraph, WM_DRAWPMMARK, MPFROMHWND(hwnd), MPFROM2SHORT( Row, Col ) ); fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( ptl.x, ptl.y ) ); break; case WM_COMMAND: switch( SHORT1FROMMP( mp1 ) ){ case IDM_GAMENEW: GBoard.NewGame(); InfoData.ShipsNotFound = GBoard.GetShipNumber(); RealPaint = TRUE; WinInvalidateRect( hwnd, NULL, TRUE ); break; case IDM_GAMESETTINGS: if( WinDlgBox( HWND_DESKTOP, hwndFrame, GameSettingsDlgProc, (HMODULE)0, IDR_GAMESETTINGSDLG, NULL ) ){ // screen must be repainted RealPaint = TRUE; WinInvalidateRect( hwnd, NULL, TRUE ); } break; case IDM_GAMEHIGH: if( !WinDlgBox( HWND_DESKTOP, hwndFrame, ShowHighDlgProc, (HMODULE)0, IDR_SHOWHIGHDLG, NULL ) ){ // user requested "Clear" if( WinMessageBox( HWND_DESKTOP, hwndMain, "Do you really want to eradicate all those " \ "arduously achieved highscores?", "Clear Highscores", 0, MB_OKCANCEL | MB_WARNING ) == MBID_OK ) InfoData.ResetHigh(); } break; case IDM_HELPINDEX: // help index WinSendMsg( hwndHelp, HM_HELP_INDEX, 0, 0 ); break; case IDM_HELPGENERAL: // general help WinSendMsg( hwndHelp, HM_EXT_HELP, 0, 0 ); break; case IDM_HELPEXTENDED: // help on help (system page) WinSendMsg( hwndHelp, HM_DISPLAY_HELP, 0, 0 ); break; case IDM_HELPKEYS: // keys help WinSendMsg( hwndHelp, HM_KEYS_HELP, 0, 0 ); break; case IDM_HELPPRODUCTINFO: ulResponse = WinDlgBox( HWND_DESKTOP, hwndFrame, ProdInfoDlgProc, (HMODULE)0, IDR_PRODINFODLG, NULL ); break; } break; case HM_QUERY_KEYS_HELP: // system asks which page to display return MRFROMSHORT( PANEL_HELPKEYS ); case HM_HELPSUBITEM_NOT_FOUND: return (MRESULT)FALSE; case WM_USER_ACK: // graphics task finished its work // DosBeep( 1000, 150 ); switch( (ULONG)mp1 ){ case WM_USER_PAINT: WinQueryPointerPos( HWND_DESKTOP, &ptl ); WinMapWindowPoints( HWND_DESKTOP, hwnd, &ptl, 1); fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( ptl.x, ptl.y ) ); // GBoard.ShowPointerPos( hwnd, ptl.x, ptl.y ); // painting has finished, square can be displayed now break; } break; case WM_SOUND_ACK: switch( (ULONG)mp1 ){ case WM_SOUND_INTRO: break; } break; default: return (MRESULT)WinDefWindowProc( hwnd, msg, mp1, mp2 ); } // end switch( msg ) return (MRESULT)WinDefWindowProc( hwnd, msg, mp1, mp2 ); } // end MRESULT EXPENTRY WndProc()