ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

main.c
Go to the documentation of this file.
00001 /*
00002  * WineMine (main.c)
00003  *
00004  * Copyright 2000 Joshua Thielen
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #define WIN32_LEAN_AND_MEAN
00022 
00023 #include <string.h>
00024 #include <time.h>
00025 #include <windows.h>
00026 #include <stdlib.h>
00027 #include <shellapi.h>
00028 #include "main.h"
00029 #include "resource.h"
00030 
00031 #include <wine/debug.h>
00032 
00033 WINE_DEFAULT_DEBUG_CHANNEL(winemine);
00034 
00035 static const DWORD wnd_style = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
00036 static const char* registry_key = "Software\\Microsoft\\WinMine";
00037 
00038 
00039 void CheckLevel( BOARD *p_board )
00040 {
00041     if( p_board->rows < BEGINNER_ROWS )
00042         p_board->rows = BEGINNER_ROWS;
00043 
00044     if( p_board->rows > MAX_ROWS )
00045         p_board->rows = MAX_ROWS;
00046 
00047     if( p_board->cols < BEGINNER_COLS )
00048         p_board->cols = BEGINNER_COLS;
00049 
00050     if( p_board->cols > MAX_COLS )
00051         p_board->cols = MAX_COLS;
00052 
00053     if( p_board->mines < BEGINNER_MINES )
00054         p_board->mines = BEGINNER_MINES;
00055 
00056     if( p_board->mines > ( p_board->cols - 1 ) * ( p_board->rows - 1 ) )
00057         p_board->mines = ( p_board->cols - 1 ) * ( p_board->rows - 1 );
00058 }
00059 
00060 static void LoadBoard( BOARD *p_board )
00061 {
00062     DWORD size;
00063     DWORD type;
00064     HKEY hkey;
00065     char data[MAX_PLAYER_NAME_SIZE+1];
00066     char key_name[8];
00067     unsigned i;
00068 
00069     RegOpenKeyEx( HKEY_CURRENT_USER, registry_key,
00070             0, KEY_QUERY_VALUE, &hkey );
00071 
00072     size = sizeof( p_board->pos.x );
00073     if( !RegQueryValueEx( hkey, "Xpos", NULL, &type,
00074             (LPBYTE) &p_board->pos.x, &size ) == ERROR_SUCCESS )
00075     p_board->pos.x = 0;
00076 
00077     size = sizeof( p_board->pos.y );
00078     if( !RegQueryValueEx( hkey, "Ypos", NULL, &type,
00079             (LPBYTE) &p_board->pos.y, &size ) == ERROR_SUCCESS )
00080         p_board->pos.y = 0;
00081 
00082     size = sizeof( p_board->rows );
00083     if( !RegQueryValueEx( hkey, "Height", NULL, &type,
00084             (LPBYTE) &p_board->rows, &size ) == ERROR_SUCCESS )
00085         p_board->rows = BEGINNER_ROWS;
00086 
00087     size = sizeof( p_board->cols );
00088     if( !RegQueryValueEx( hkey, "Width", NULL, &type,
00089             (LPBYTE) &p_board->cols, &size ) == ERROR_SUCCESS )
00090         p_board->cols = BEGINNER_COLS;
00091 
00092     size = sizeof( p_board->mines );
00093     if( !RegQueryValueEx( hkey, "Mines", NULL, &type,
00094             (LPBYTE) &p_board->mines, &size ) == ERROR_SUCCESS )
00095         p_board->mines = BEGINNER_MINES;
00096 
00097     size = sizeof( p_board->difficulty );
00098     if( !RegQueryValueEx( hkey, "Difficulty", NULL, &type,
00099             (LPBYTE) &p_board->difficulty, &size ) == ERROR_SUCCESS )
00100         p_board->difficulty = BEGINNER;
00101 
00102     size = sizeof( p_board->IsMarkQ );
00103     if( !RegQueryValueEx( hkey, "Mark", NULL, &type,
00104             (LPBYTE) &p_board->IsMarkQ, &size ) == ERROR_SUCCESS )
00105         p_board->IsMarkQ = TRUE;
00106 
00107     for( i = 0; i < 3; i++ ) {
00108         wsprintf( key_name, "Name%d", i+1 );
00109         size = sizeof( data );
00110         if( RegQueryValueEx( hkey, key_name, NULL, &type,
00111                 (LPBYTE) data, &size ) == ERROR_SUCCESS )
00112             lstrcpynA( p_board->best_name[i], data, sizeof(p_board->best_name[i]) );
00113         else
00114             LoadString( p_board->hInst, IDS_NOBODY, p_board->best_name[i], MAX_PLAYER_NAME_SIZE+1 );
00115     }
00116 
00117     for( i = 0; i < 3; i++ ) {
00118         wsprintf( key_name, "Time%d", i+1 );
00119         size = sizeof( p_board->best_time[i] );
00120         if( !RegQueryValueEx( hkey, key_name, NULL, &type,
00121                 (LPBYTE) &p_board->best_time[i], &size ) == ERROR_SUCCESS )
00122             p_board->best_time[i] = 999;
00123     }
00124     RegCloseKey( hkey );
00125 }
00126 
00127 static void InitBoard( BOARD *p_board )
00128 {
00129     HMENU hMenu;
00130 
00131     p_board->hMinesBMP = LoadBitmap( p_board->hInst, "mines");
00132     p_board->hFacesBMP = LoadBitmap( p_board->hInst, "faces");
00133     p_board->hLedsBMP = LoadBitmap( p_board->hInst, "leds");
00134 
00135     LoadBoard( p_board );
00136 
00137     hMenu = GetMenu( p_board->hWnd );
00138     CheckMenuItem( hMenu, IDM_BEGINNER + (unsigned) p_board->difficulty,
00139             MF_CHECKED );
00140     if( p_board->IsMarkQ )
00141         CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
00142     else
00143         CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
00144     CheckLevel( p_board );
00145 }
00146 
00147 static void SaveBoard( BOARD *p_board )
00148 {
00149     HKEY hkey;
00150     unsigned i;
00151     char data[MAX_PLAYER_NAME_SIZE+1];
00152     char key_name[8];
00153 
00154     if( RegCreateKeyEx( HKEY_CURRENT_USER, registry_key,
00155             0, NULL,
00156                 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
00157                 &hkey, NULL ) != ERROR_SUCCESS)
00158         return;
00159 
00160     RegSetValueEx( hkey, "Xpos", 0, REG_DWORD, (LPBYTE) &p_board->pos.x, sizeof(p_board->pos.x) );
00161     RegSetValueEx( hkey, "Ypos", 0, REG_DWORD, (LPBYTE) &p_board->pos.y, sizeof(p_board->pos.y) );
00162     RegSetValueEx( hkey, "Difficulty", 0, REG_DWORD, (LPBYTE) &p_board->difficulty, sizeof(p_board->difficulty) );
00163     RegSetValueEx( hkey, "Height", 0, REG_DWORD, (LPBYTE) &p_board->rows, sizeof(p_board->rows) );
00164     RegSetValueEx( hkey, "Width", 0, REG_DWORD, (LPBYTE) &p_board->cols, sizeof(p_board->cols) );
00165     RegSetValueEx( hkey, "Mines", 0, REG_DWORD, (LPBYTE) &p_board->mines, sizeof(p_board->mines) );
00166     RegSetValueEx( hkey, "Mark", 0, REG_DWORD, (LPBYTE) &p_board->IsMarkQ, sizeof(p_board->IsMarkQ) );
00167 
00168     for( i = 0; i < 3; i++ ) {
00169         wsprintf( key_name, "Name%u", i+1 );
00170         lstrcpyn( data, p_board->best_name[i], sizeof( data ) );
00171         RegSetValueEx( hkey, key_name, 0, REG_SZ, (LPBYTE) data, strlen(data)+1 );
00172     }
00173 
00174     for( i = 0; i < 3; i++ ) {
00175         wsprintf( key_name, "Time%u", i+1 );
00176         RegSetValueEx( hkey, key_name, 0, REG_DWORD, (LPBYTE) &p_board->best_time[i], sizeof(p_board->best_time[i]) );
00177     }
00178     RegCloseKey( hkey );
00179 }
00180 
00181 static void DestroyBoard( BOARD *p_board )
00182 {
00183     DeleteObject( p_board->hFacesBMP );
00184     DeleteObject( p_board->hLedsBMP );
00185     DeleteObject( p_board->hMinesBMP );
00186 }
00187 
00188 static void SetDifficulty( BOARD *p_board, DIFFICULTY difficulty )
00189 {
00190     HMENU hMenu;
00191 
00192     if ( difficulty == CUSTOM )
00193         if (DialogBoxParam( p_board->hInst, "DLG_CUSTOM", p_board->hWnd,
00194                     CustomDlgProc, (LPARAM) p_board) != 0)
00195            return;
00196 
00197     hMenu = GetMenu( p_board->hWnd );
00198     CheckMenuItem( hMenu, IDM_BEGINNER + p_board->difficulty, MF_UNCHECKED );
00199     p_board->difficulty = difficulty;
00200     CheckMenuItem( hMenu, IDM_BEGINNER + difficulty, MF_CHECKED );
00201 
00202     switch( difficulty ) {
00203     case BEGINNER:
00204         p_board->cols = BEGINNER_COLS;
00205         p_board->rows = BEGINNER_ROWS;
00206         p_board->mines = BEGINNER_MINES;
00207         break;
00208 
00209     case ADVANCED:
00210         p_board->cols = ADVANCED_COLS;
00211         p_board->rows = ADVANCED_ROWS;
00212         p_board->mines = ADVANCED_MINES;
00213         break;
00214 
00215     case EXPERT:
00216         p_board->cols = EXPERT_COLS;
00217         p_board->rows = EXPERT_ROWS;
00218 
00219         p_board->mines = EXPERT_MINES;
00220         break;
00221 
00222     case CUSTOM:
00223         break;
00224     }
00225 }
00226 
00227 static void ShiftBetween(LONG* x, LONG* y, LONG a, LONG b)
00228 {
00229     if (*x < a) {
00230     *y += a - *x;
00231     *x = a;
00232     }
00233     else if (*y > b) {
00234     *x -= *y - b;
00235     *y = b;
00236     }
00237 }
00238 
00239 static void MoveOnScreen(RECT* rect)
00240 {
00241     HMONITOR hMonitor;
00242     MONITORINFO mi;
00243 
00244     /* find the nearest monitor ... */
00245     hMonitor = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST);
00246 
00247     /* ... and move it into the work area (ie excluding task bar)*/
00248     mi.cbSize = sizeof(mi);
00249     GetMonitorInfo(hMonitor, &mi);
00250 
00251     ShiftBetween(&rect->left, &rect->right, mi.rcWork.left, mi.rcWork.right);
00252     ShiftBetween(&rect->top, &rect->bottom, mi.rcWork.top, mi.rcWork.bottom);
00253 }
00254 
00255 static void CreateBoard( BOARD *p_board )
00256 {
00257     int left, top, bottom, right;
00258     unsigned col, row;
00259     RECT wnd_rect;
00260 
00261     p_board->mb = MB_NONE;
00262     p_board->boxes_left = p_board->cols * p_board->rows - p_board->mines;
00263     p_board->num_flags = 0;
00264 
00265     /* Create the boxes...
00266      * We actually create them with an empty border,
00267      * so special care doesn't have to be taken on the edges
00268      */
00269     for( col = 0; col <= p_board->cols + 1; col++ )
00270       for( row = 0; row <= p_board->rows + 1; row++ ) {
00271         p_board->box[col][row].IsPressed = FALSE;
00272         p_board->box[col][row].IsMine = FALSE;
00273         p_board->box[col][row].FlagType = NORMAL;
00274         p_board->box[col][row].NumMines = 0;
00275       }
00276 
00277     p_board->width = p_board->cols * MINE_WIDTH + BOARD_WMARGIN * 2;
00278 
00279     p_board->height = p_board->rows * MINE_HEIGHT + LED_HEIGHT
00280         + BOARD_HMARGIN * 3;
00281 
00282     /* setting the mines rectangle boundary */
00283     left = BOARD_WMARGIN;
00284     top = BOARD_HMARGIN * 2 + LED_HEIGHT;
00285     right = left + p_board->cols * MINE_WIDTH;
00286     bottom = top + p_board->rows * MINE_HEIGHT;
00287     SetRect( &p_board->mines_rect, left, top, right, bottom );
00288 
00289     /* setting the face rectangle boundary */
00290     left = p_board->width / 2 - FACE_WIDTH / 2;
00291     top = BOARD_HMARGIN;
00292     right = left + FACE_WIDTH;
00293     bottom = top + FACE_HEIGHT;
00294     SetRect( &p_board->face_rect, left, top, right, bottom );
00295 
00296     /* setting the timer rectangle boundary */
00297     left = BOARD_WMARGIN;
00298     top = BOARD_HMARGIN;
00299     right = left + LED_WIDTH * 3;
00300     bottom = top + LED_HEIGHT;
00301     SetRect( &p_board->timer_rect, left, top, right, bottom );
00302 
00303     /* setting the counter rectangle boundary */
00304     left =  p_board->width - BOARD_WMARGIN - LED_WIDTH * 3;
00305     top = BOARD_HMARGIN;
00306     right = p_board->width - BOARD_WMARGIN;
00307     bottom = top + LED_HEIGHT;
00308     SetRect( &p_board->counter_rect, left, top, right, bottom );
00309 
00310     p_board->status = WAITING;
00311     p_board->face_bmp = SMILE_BMP;
00312     p_board->time = 0;
00313 
00314     wnd_rect.left   = p_board->pos.x;
00315     wnd_rect.right  = p_board->pos.x + p_board->width;
00316     wnd_rect.top    = p_board->pos.y;
00317     wnd_rect.bottom = p_board->pos.y + p_board->height;
00318     AdjustWindowRect(&wnd_rect, wnd_style, TRUE);
00319 
00320     /* Make sure the window is completely on the screen */
00321     MoveOnScreen(&wnd_rect);
00322     MoveWindow( p_board->hWnd, wnd_rect.left, wnd_rect.top,
00323         wnd_rect.right - wnd_rect.left,
00324         wnd_rect.bottom - wnd_rect.top,
00325         TRUE );
00326     RedrawWindow( p_board->hWnd, NULL, 0,
00327           RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
00328 }
00329 
00330 
00331 /* Randomly places mines everywhere except the selected box. */
00332 static void PlaceMines ( BOARD *p_board, int selected_col, int selected_row )
00333 {
00334     int i, j;
00335     unsigned col, row;
00336 
00337     srand( (unsigned) time( NULL ) );
00338 
00339     /* Temporarily place a mine at the selected box until all the other
00340      * mines are placed, this avoids checking in the mine creation loop. */
00341     p_board->box[selected_col][selected_row].IsMine = TRUE;
00342 
00343     /* create mines */
00344     i = 0;
00345     while( (unsigned) i < p_board->mines ) {
00346         col = (int) (p_board->cols * (float) rand() / RAND_MAX + 1);
00347         row = (int) (p_board->rows * (float) rand() / RAND_MAX + 1);
00348 
00349         if( !p_board->box[col][row].IsMine ) {
00350             i++;
00351             p_board->box[col][row].IsMine = TRUE;
00352         }
00353     }
00354 
00355     /* Remove temporarily placed mine for selected box */
00356     p_board->box[selected_col][selected_row].IsMine = FALSE;
00357 
00358     /*
00359      * Now we label the remaining boxes with the
00360      * number of mines surrounding them.
00361      */
00362     for( col = 1; col < p_board->cols + 1; col++ )
00363     for( row = 1; row < p_board->rows + 1; row++ ) {
00364         for( i = -1; i <= 1; i++ )
00365         for( j = -1; j <= 1; j++ ) {
00366             if( p_board->box[col + i][row + j].IsMine ) {
00367                 p_board->box[col][row].NumMines++ ;
00368             }
00369         }
00370     }
00371 }
00372 
00373 static void DrawMine( HDC hdc, HDC hMemDC, BOARD *p_board, unsigned col, unsigned row, BOOL IsPressed )
00374 {
00375     MINEBMP_OFFSET offset = BOX_BMP;
00376 
00377     if( col == 0 || col > p_board->cols || row == 0 || row > p_board->rows )
00378            return;
00379 
00380     if( p_board->status == GAMEOVER ) {
00381         if( p_board->box[col][row].IsMine ) {
00382             switch( p_board->box[col][row].FlagType ) {
00383             case FLAG:
00384                 offset = FLAG_BMP;
00385                 break;
00386             case COMPLETE:
00387                 offset = EXPLODE_BMP;
00388                 break;
00389             case QUESTION:
00390                 /* fall through */
00391             case NORMAL:
00392                 offset = MINE_BMP;
00393             }
00394         } else {
00395             switch( p_board->box[col][row].FlagType ) {
00396             case QUESTION:
00397                 offset = QUESTION_BMP;
00398                 break;
00399             case FLAG:
00400                 offset = WRONG_BMP;
00401                 break;
00402             case NORMAL:
00403                 offset = BOX_BMP;
00404                 break;
00405             case COMPLETE:
00406                 /* Do nothing */
00407                 break;
00408             default:
00409                 WINE_TRACE("Unknown FlagType during game over in DrawMine\n");
00410                 break;
00411             }
00412         }
00413     } else {    /* WAITING or PLAYING */
00414         switch( p_board->box[col][row].FlagType ) {
00415         case QUESTION:
00416             if( !IsPressed )
00417                 offset = QUESTION_BMP;
00418             else
00419                 offset = QPRESS_BMP;
00420             break;
00421         case FLAG:
00422             offset = FLAG_BMP;
00423             break;
00424         case NORMAL:
00425             if( !IsPressed )
00426                 offset = BOX_BMP;
00427             else
00428                 offset = MPRESS_BMP;
00429             break;
00430         case COMPLETE:
00431             /* Do nothing */
00432             break;
00433         default:
00434             WINE_TRACE("Unknown FlagType while playing in DrawMine\n");
00435             break;
00436         }
00437     }
00438 
00439     if( p_board->box[col][row].FlagType == COMPLETE
00440         && !p_board->box[col][row].IsMine )
00441           offset = (MINEBMP_OFFSET) p_board->box[col][row].NumMines;
00442 
00443     BitBlt( hdc,
00444             (col - 1) * MINE_WIDTH + p_board->mines_rect.left,
00445             (row - 1) * MINE_HEIGHT + p_board->mines_rect.top,
00446             MINE_WIDTH, MINE_HEIGHT,
00447             hMemDC, 0, offset * MINE_HEIGHT, SRCCOPY );
00448 }
00449 
00450 static void DrawMines ( HDC hdc, HDC hMemDC, BOARD *p_board )
00451 {
00452     HGDIOBJ hOldObj;
00453     unsigned col, row;
00454     hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
00455 
00456     for( row = 1; row <= p_board->rows; row++ ) {
00457       for( col = 1; col <= p_board->cols; col++ ) {
00458         DrawMine( hdc, hMemDC, p_board, col, row, FALSE );
00459       }
00460     }
00461     SelectObject( hMemDC, hOldObj );
00462 }
00463 
00464 static void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y )
00465 {
00466     HGDIOBJ hOldObj;
00467     unsigned led[3], i;
00468     int count;
00469 
00470     count = number;
00471     if( count < 1000 ) {
00472         if( count >= 0 ) {
00473             led[0] = count / 100 ;
00474             count -= led[0] * 100;
00475         }
00476         else {
00477             led[0] = 10; /* negative sign */
00478             count = -count;
00479         }
00480         led[1] = count / 10;
00481         count -= led[1] * 10;
00482         led[2] = count;
00483     }
00484     else {
00485         for( i = 0; i < 3; i++ )
00486             led[i] = 10;
00487     }
00488 
00489     hOldObj = SelectObject (hMemDC, p_board->hLedsBMP);
00490 
00491     for( i = 0; i < 3; i++ ) {
00492         BitBlt( hdc,
00493             i * LED_WIDTH + x,
00494             y,
00495             LED_WIDTH,
00496             LED_HEIGHT,
00497             hMemDC,
00498             0,
00499             led[i] * LED_HEIGHT,
00500             SRCCOPY);
00501     }
00502 
00503     SelectObject( hMemDC, hOldObj );
00504 }
00505 
00506 
00507 static void DrawFace( HDC hdc, HDC hMemDC, BOARD *p_board )
00508 {
00509     HGDIOBJ hOldObj;
00510 
00511     hOldObj = SelectObject (hMemDC, p_board->hFacesBMP);
00512 
00513     BitBlt( hdc,
00514         p_board->face_rect.left,
00515         p_board->face_rect.top,
00516         FACE_WIDTH,
00517         FACE_HEIGHT,
00518         hMemDC, 0, p_board->face_bmp * FACE_HEIGHT, SRCCOPY);
00519 
00520     SelectObject( hMemDC, hOldObj );
00521 }
00522 
00523 
00524 static void DrawBoard( HDC hdc, HDC hMemDC, PAINTSTRUCT *ps, BOARD *p_board )
00525 {
00526     RECT tmp_rect;
00527 
00528     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->counter_rect ) )
00529         DrawLeds( hdc, hMemDC, p_board, p_board->mines - p_board->num_flags,
00530                   p_board->counter_rect.left,
00531                   p_board->counter_rect.top );
00532 
00533     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->timer_rect ) )
00534         DrawLeds( hdc, hMemDC, p_board, p_board->time,
00535                   p_board->timer_rect.left,
00536                   p_board->timer_rect.top );
00537 
00538     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->face_rect ) )
00539         DrawFace( hdc, hMemDC, p_board );
00540 
00541     if( IntersectRect( &tmp_rect, &ps->rcPaint, &p_board->mines_rect ) )
00542         DrawMines( hdc, hMemDC, p_board );
00543 }
00544 
00545 
00546 static void AddFlag( BOARD *p_board, unsigned col, unsigned row )
00547 {
00548     if( p_board->box[col][row].FlagType != COMPLETE ) {
00549         switch( p_board->box[col][row].FlagType ) {
00550         case FLAG:
00551             if( p_board->IsMarkQ )
00552                 p_board->box[col][row].FlagType = QUESTION;
00553             else
00554                 p_board->box[col][row].FlagType = NORMAL;
00555             p_board->num_flags--;
00556             break;
00557 
00558         case QUESTION:
00559             p_board->box[col][row].FlagType = NORMAL;
00560             break;
00561 
00562         default:
00563             p_board->box[col][row].FlagType = FLAG;
00564             p_board->num_flags++;
00565         }
00566     }
00567 }
00568 
00569 
00570 static void UnpressBox( BOARD *p_board, unsigned col, unsigned row )
00571 {
00572     HDC hdc;
00573     HGDIOBJ hOldObj;
00574     HDC hMemDC;
00575 
00576     hdc = GetDC( p_board->hWnd );
00577     hMemDC = CreateCompatibleDC( hdc );
00578     hOldObj = SelectObject( hMemDC, p_board->hMinesBMP );
00579 
00580     DrawMine( hdc, hMemDC, p_board, col, row, FALSE );
00581 
00582     SelectObject( hMemDC, hOldObj );
00583     DeleteDC( hMemDC );
00584     ReleaseDC( p_board->hWnd, hdc );
00585 }
00586 
00587 
00588 static void UnpressBoxes( BOARD *p_board, unsigned col, unsigned row )
00589 {
00590     int i, j;
00591 
00592     for( i = -1; i <= 1; i++ )
00593       for( j = -1; j <= 1; j++ ) {
00594         UnpressBox( p_board, col + i, row + j );
00595       }
00596 }
00597 
00598 
00599 static void PressBox( BOARD *p_board, unsigned col, unsigned row )
00600 {
00601     HDC hdc;
00602     HGDIOBJ hOldObj;
00603     HDC hMemDC;
00604 
00605     hdc = GetDC( p_board->hWnd );
00606     hMemDC = CreateCompatibleDC( hdc );
00607     hOldObj = SelectObject (hMemDC, p_board->hMinesBMP);
00608 
00609     DrawMine( hdc, hMemDC, p_board, col, row, TRUE );
00610 
00611     SelectObject( hMemDC, hOldObj );
00612     DeleteDC( hMemDC );
00613     ReleaseDC( p_board->hWnd, hdc );
00614 }
00615 
00616 
00617 static void PressBoxes( BOARD *p_board, unsigned col, unsigned row )
00618 {
00619     int i, j;
00620 
00621     for( i = -1; i <= 1; i++ )
00622       for( j = -1; j <= 1; j++ ) {
00623         p_board->box[col + i][row + j].IsPressed = TRUE;
00624         PressBox( p_board, col + i, row + j );
00625     }
00626 
00627     for( i = -1; i <= 1; i++ )
00628       for( j = -1; j <= 1; j++ ) {
00629         if( !p_board->box[p_board->press.x + i][p_board->press.y + j].IsPressed )
00630             UnpressBox( p_board, p_board->press.x + i, p_board->press.y + j );
00631     }
00632 
00633     for( i = -1; i <= 1; i++ )
00634       for( j = -1; j <= 1; j++ ) {
00635         p_board->box[col + i][row + j].IsPressed = FALSE;
00636         PressBox( p_board, col + i, row + j );
00637     }
00638 
00639     p_board->press.x = col;
00640     p_board->press.y = row;
00641 }
00642 
00643 
00644 static void CompleteBox( BOARD *p_board, unsigned col, unsigned row )
00645 {
00646     int i, j;
00647 
00648     if( p_board->box[col][row].FlagType != COMPLETE &&
00649             p_board->box[col][row].FlagType != FLAG &&
00650             col > 0 && col < p_board->cols + 1 &&
00651             row > 0 && row < p_board->rows + 1 ) {
00652         p_board->box[col][row].FlagType = COMPLETE;
00653 
00654         if( p_board->box[col][row].IsMine ) {
00655             p_board->face_bmp = DEAD_BMP;
00656             p_board->status = GAMEOVER;
00657         }
00658         else if( p_board->status != GAMEOVER )
00659             p_board->boxes_left--;
00660 
00661         if( p_board->box[col][row].NumMines == 0 )
00662         {
00663             for( i = -1; i <= 1; i++ )
00664             for( j = -1; j <= 1; j++ )
00665                 CompleteBox( p_board, col + i, row + j  );
00666         }
00667     }
00668 }
00669 
00670 
00671 static void CompleteBoxes( BOARD *p_board, unsigned col, unsigned row )
00672 {
00673     unsigned numFlags = 0;
00674     int i, j;
00675 
00676     if( p_board->box[col][row].FlagType == COMPLETE ) {
00677         for( i = -1; i <= 1; i++ )
00678           for( j = -1; j <= 1; j++ ) {
00679             if( p_board->box[col+i][row+j].FlagType == FLAG )
00680                 numFlags++;
00681           }
00682 
00683         if( numFlags == p_board->box[col][row].NumMines ) {
00684             for( i = -1; i <= 1; i++ )
00685               for( j = -1; j <= 1; j++ ) {
00686                 if( p_board->box[col+i][row+j].FlagType != FLAG )
00687                     CompleteBox( p_board, col+i, row+j );
00688               }
00689         }
00690     }
00691 }
00692 
00693 
00694 static void TestMines( BOARD *p_board, POINT pt, int msg )
00695 {
00696     BOOL draw = TRUE;
00697     int col, row;
00698 
00699     col = (pt.x - p_board->mines_rect.left) / MINE_WIDTH + 1;
00700     row = (pt.y - p_board->mines_rect.top ) / MINE_HEIGHT + 1;
00701 
00702     switch ( msg ) {
00703     case WM_LBUTTONDOWN:
00704         if( p_board->press.x != col || p_board->press.y != row ) {
00705             UnpressBox( p_board,
00706                     p_board->press.x, p_board->press.y );
00707             p_board->press.x = col;
00708             p_board->press.y = row;
00709             PressBox( p_board, col, row );
00710         }
00711         draw = FALSE;
00712         break;
00713 
00714     case WM_LBUTTONUP:
00715         if( p_board->press.x != col || p_board->press.y != row )
00716             UnpressBox( p_board,
00717                     p_board->press.x, p_board->press.y );
00718         p_board->press.x = 0;
00719         p_board->press.y = 0;
00720         if( p_board->box[col][row].FlagType != FLAG
00721             && p_board->status != PLAYING )
00722         {
00723             p_board->status = PLAYING;
00724             PlaceMines( p_board, col, row );
00725         }
00726         CompleteBox( p_board, col, row );
00727         break;
00728 
00729     case WM_MBUTTONDOWN:
00730         PressBoxes( p_board, col, row );
00731         draw = FALSE;
00732         break;
00733 
00734     case WM_MBUTTONUP:
00735         if( p_board->press.x != col || p_board->press.y != row )
00736             UnpressBoxes( p_board,
00737                     p_board->press.x, p_board->press.y );
00738         p_board->press.x = 0;
00739         p_board->press.y = 0;
00740         CompleteBoxes( p_board, col, row );
00741         break;
00742 
00743     case WM_RBUTTONDOWN:
00744         AddFlag( p_board, col, row );
00745         break;
00746     default:
00747         WINE_TRACE("Unknown message type received in TestMines\n");
00748         break;
00749     }
00750 
00751     if( draw )
00752     {
00753         RedrawWindow( p_board->hWnd, NULL, 0,
00754             RDW_INVALIDATE | RDW_UPDATENOW );
00755     }
00756 }
00757 
00758 
00759 static void TestFace( BOARD *p_board, POINT pt, int msg )
00760 {
00761     if( p_board->status == PLAYING || p_board->status == WAITING ) {
00762         if( msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN )
00763             p_board->face_bmp = OOH_BMP;
00764         else p_board->face_bmp = SMILE_BMP;
00765     }
00766     else if( p_board->status == GAMEOVER )
00767         p_board->face_bmp = DEAD_BMP;
00768     else if( p_board->status == WON )
00769             p_board->face_bmp = COOL_BMP;
00770 
00771     if( PtInRect( &p_board->face_rect, pt ) ) {
00772         if( msg == WM_LBUTTONDOWN )
00773             p_board->face_bmp = SPRESS_BMP;
00774 
00775         if( msg == WM_LBUTTONUP )
00776             CreateBoard( p_board );
00777     }
00778 
00779     RedrawWindow( p_board->hWnd, &p_board->face_rect, 0,
00780         RDW_INVALIDATE | RDW_UPDATENOW );
00781 }
00782 
00783 
00784 static void TestBoard( HWND hWnd, BOARD *p_board, int x, int y, int msg )
00785 {
00786     POINT pt;
00787     unsigned col,row;
00788 
00789     pt.x = x;
00790     pt.y = y;
00791 
00792     if( PtInRect( &p_board->mines_rect, pt ) && p_board->status != GAMEOVER
00793     && p_board->status != WON )
00794         TestMines( p_board, pt, msg );
00795     else {
00796         UnpressBoxes( p_board,
00797             p_board->press.x,
00798             p_board->press.y );
00799         p_board->press.x = 0;
00800         p_board->press.y = 0;
00801     }
00802 
00803     if( p_board->boxes_left == 0 ) {
00804         p_board->status = WON;
00805 
00806         if (p_board->num_flags < p_board->mines) {
00807             for( row = 1; row <= p_board->rows; row++ ) {
00808                 for( col = 1; col <= p_board->cols; col++ ) {
00809                     if (p_board->box[col][row].IsMine && p_board->box[col][row].FlagType != FLAG)
00810                         p_board->box[col][row].FlagType = FLAG;
00811                 }
00812             }
00813 
00814             p_board->num_flags = p_board->mines;
00815 
00816             RedrawWindow( p_board->hWnd, NULL, 0,
00817                 RDW_INVALIDATE | RDW_UPDATENOW );
00818         }
00819 
00820         if( p_board->difficulty != CUSTOM &&
00821                     p_board->time < p_board->best_time[p_board->difficulty] ) {
00822             p_board->best_time[p_board->difficulty] = p_board->time;
00823 
00824             DialogBoxParam( p_board->hInst, "DLG_CONGRATS", hWnd,
00825                     CongratsDlgProc, (LPARAM) p_board);
00826 
00827             DialogBoxParam( p_board->hInst, "DLG_TIMES", hWnd,
00828                     TimesDlgProc, (LPARAM) p_board);
00829         }
00830     }
00831     TestFace( p_board, pt, msg );
00832 }
00833 
00834 
00835 static LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
00836 {
00837     HDC hdc;
00838     PAINTSTRUCT ps;
00839     HMENU hMenu;
00840     static BOARD board;
00841 
00842     switch( msg ) {
00843     case WM_CREATE:
00844         board.hInst = ((LPCREATESTRUCT) lParam)->hInstance;
00845         board.hWnd = hWnd;
00846         InitBoard( &board );
00847         CreateBoard( &board );
00848         return 0;
00849 
00850     case WM_PAINT:
00851       {
00852         HDC hMemDC;
00853 
00854         WINE_TRACE("WM_PAINT\n");
00855         hdc = BeginPaint( hWnd, &ps );
00856         hMemDC = CreateCompatibleDC( hdc );
00857 
00858         DrawBoard( hdc, hMemDC, &ps, &board );
00859 
00860         DeleteDC( hMemDC );
00861         EndPaint( hWnd, &ps );
00862 
00863         return 0;
00864       }
00865 
00866     case WM_MOVE:
00867         WINE_TRACE("WM_MOVE\n");
00868         board.pos.x = (short)LOWORD(lParam);
00869         board.pos.y = (short)HIWORD(lParam);
00870         return 0;
00871 
00872     case WM_DESTROY:
00873         SaveBoard( &board );
00874         DestroyBoard( &board );
00875         PostQuitMessage( 0 );
00876         return 0;
00877 
00878     case WM_TIMER:
00879         if( board.status == PLAYING ) {
00880             board.time++;
00881         RedrawWindow( hWnd, &board.timer_rect, 0,
00882               RDW_INVALIDATE | RDW_UPDATENOW );
00883         }
00884         return 0;
00885 
00886     case WM_LBUTTONDOWN:
00887         WINE_TRACE("WM_LBUTTONDOWN\n");
00888         if( wParam & (MK_RBUTTON | MK_SHIFT) )
00889             msg = WM_MBUTTONDOWN;
00890         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
00891         SetCapture( hWnd );
00892         return 0;
00893 
00894     case WM_LBUTTONUP:
00895         WINE_TRACE("WM_LBUTTONUP\n");
00896         if( wParam & (MK_RBUTTON | MK_SHIFT) )
00897             msg = WM_MBUTTONUP;
00898         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
00899         ReleaseCapture();
00900         return 0;
00901 
00902     case WM_RBUTTONDOWN:
00903         WINE_TRACE("WM_RBUTTONDOWN\n");
00904         if( wParam & MK_LBUTTON ) {
00905             board.press.x = 0;
00906             board.press.y = 0;
00907             msg = WM_MBUTTONDOWN;
00908         }
00909         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
00910         return 0;
00911 
00912     case WM_RBUTTONUP:
00913         WINE_TRACE("WM_RBUTTONUP\n");
00914         if( wParam & MK_LBUTTON )
00915             msg = WM_MBUTTONUP;
00916         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
00917         return 0;
00918 
00919     case WM_MBUTTONDOWN:
00920         WINE_TRACE("WM_MBUTTONDOWN\n");
00921         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
00922         return 0;
00923 
00924     case WM_MBUTTONUP:
00925         WINE_TRACE("WM_MBUTTONUP\n");
00926         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam), msg );
00927         return 0;
00928 
00929     case WM_MOUSEMOVE:
00930     {
00931         if( ( wParam & MK_MBUTTON ) ||
00932             ( ( wParam & MK_LBUTTON ) && ( wParam & MK_RBUTTON ) ) ) {
00933             msg = WM_MBUTTONDOWN;
00934         }
00935         else if( wParam & MK_LBUTTON ) {
00936             msg = WM_LBUTTONDOWN;
00937         }
00938         else {
00939             return 0;
00940         }
00941 
00942         TestBoard( hWnd, &board, (short)LOWORD(lParam), (short)HIWORD(lParam),  msg );
00943 
00944         return 0;
00945     }
00946 
00947     case WM_COMMAND:
00948         switch(LOWORD(wParam)) {
00949         case IDM_NEW:
00950             CreateBoard( &board );
00951             return 0;
00952 
00953         case IDM_MARKQ:
00954             hMenu = GetMenu( hWnd );
00955             board.IsMarkQ = !board.IsMarkQ;
00956             if( board.IsMarkQ )
00957                 CheckMenuItem( hMenu, IDM_MARKQ, MF_CHECKED );
00958             else
00959                 CheckMenuItem( hMenu, IDM_MARKQ, MF_UNCHECKED );
00960             return 0;
00961 
00962         case IDM_BEGINNER:
00963             SetDifficulty( &board, BEGINNER );
00964             CreateBoard( &board );
00965             return 0;
00966 
00967         case IDM_ADVANCED:
00968             SetDifficulty( &board, ADVANCED );
00969             CreateBoard( &board );
00970             return 0;
00971 
00972         case IDM_EXPERT:
00973             SetDifficulty( &board, EXPERT );
00974             CreateBoard( &board );
00975             return 0;
00976 
00977         case IDM_CUSTOM:
00978             SetDifficulty( &board, CUSTOM );
00979             CreateBoard( &board );
00980             return 0;
00981 
00982         case IDM_EXIT:
00983             SendMessage( hWnd, WM_CLOSE, 0, 0);
00984             return 0;
00985 
00986         case IDM_TIMES:
00987             DialogBoxParam( board.hInst, "DLG_TIMES", hWnd,
00988                     TimesDlgProc, (LPARAM) &board);
00989             return 0;
00990 
00991         case IDM_ABOUT:
00992         {
00993             WCHAR appname[256], other[256];
00994             LoadStringW( board.hInst, IDS_APPNAME, appname, sizeof(appname)/sizeof(WCHAR) );
00995             LoadStringW( board.hInst, IDS_ABOUT, other, sizeof(other)/sizeof(WCHAR) );
00996             ShellAboutW( hWnd, appname, other,
00997                          LoadImageA( board.hInst, "WINEMINE", IMAGE_ICON, 48, 48, LR_SHARED ));
00998             return 0;
00999         }
01000         default:
01001             WINE_TRACE("Unknown WM_COMMAND command message received\n");
01002             break;
01003         }
01004     }
01005     return( DefWindowProc( hWnd, msg, wParam, lParam ));
01006 }
01007 
01008 int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow )
01009 {
01010     MSG msg;
01011     WNDCLASSEX wc;
01012     HWND hWnd;
01013     HACCEL haccel;
01014     char appname[20];
01015 
01016     LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));
01017 
01018     wc.cbSize = sizeof(wc);
01019     wc.style = 0;
01020     wc.lpfnWndProc = MainProc;
01021     wc.cbClsExtra = 0;
01022     wc.cbWndExtra = 0;
01023     wc.hInstance = hInst;
01024     wc.hIcon = LoadIcon( hInst, "WINEMINE" );
01025     wc.hCursor = LoadCursor( 0, IDI_APPLICATION );
01026     wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); //MOD for ROS
01027     wc.lpszMenuName = "MENU_WINEMINE";
01028     wc.lpszClassName = appname;
01029     wc.hIconSm = LoadImage( hInst, "WINEMINE", IMAGE_ICON,
01030                             GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
01031 
01032     if (!RegisterClassEx(&wc)) ExitProcess(1);
01033     hWnd = CreateWindow( appname, appname,
01034     wnd_style,
01035         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
01036         0, 0, hInst, NULL );
01037 
01038     if (!hWnd) ExitProcess(1);
01039 
01040     ShowWindow( hWnd, cmdshow );
01041     UpdateWindow( hWnd );
01042 
01043     haccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDA_WINEMINE) );
01044     SetTimer( hWnd, ID_TIMER, 1000, NULL );
01045 
01046     while( GetMessage(&msg, 0, 0, 0) ) {
01047         if (!TranslateAccelerator( hWnd, haccel, &msg ))
01048             TranslateMessage( &msg );
01049 
01050         DispatchMessage( &msg );
01051     }
01052     return msg.wParam;
01053 }

Generated on Sun May 27 2012 04:16:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.