API Windows en C

Code d'un Othello

CGI

- Titre : API Windows en C

- Auteur : CGI

- Parution : 5 juin 2005

- Licence : Copyright 2002-2020 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels. Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document. De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.

Sommaire

- I. Introduction

- II. Code complet

I - Introduction

Code d'un othello en pure Windows API. (Mode 2 joueurs en réseau). Avec utilisation d'un fichier ressources .rc

II - Code complet

ressources.rc :

#include <windows.h>
#include "resources.h"

LEMENU MENU
BEGIN
POPUP "Fichier"
BEGIN
MENUITEM "Start", IDM_NEW
MENUITEM "Stop", IDM_STOP
MENUITEM "Paramètres réseau...", IDM_PARAM
MENUITEM SEPARATOR
MENUITEM "A propos...", IDM_ABOUT
MENUITEM "&Quitter", IDM_QUIT
END
END

DIALOG1 DIALOGEX 30, 60, 210, 120
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL         "Serveur",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,78,15,41,10
CONTROL         "Client",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,27,15,34,10
CONTROL         "",IDC_IPADDRESS1,"SysIPAddress32",WS_TABSTOP,78,39,100,15
LTEXT           "Adresse IP",-1,27,41,36,8
DEFPUSHBUTTON   "OK",IDOK,37,82,50,14
PUSHBUTTON      "Annuler",IDCANCEL,121,82,50,14
END

ressources.h :

#define IDM_QUIT        1
#define IDM_NEW         2
#define IDM_PARAM       3
#define IDM_ABOUT       4
#define IDM_STOP        5

#define IDD_DIALOG1     101

#define IDC_RADIO1      1000
#define IDC_RADIO2      1001
#define IDC_EDIT1       1002
#define IDC_IPADDRESS1  1003
#define IDC_BUTTON1     1004
#define IDC_BUTTON2     1005

main.c :

#include <windows.h>
#include <commctrl.h>
#include "resources.h"

#define LARG 64

#define NBC_X 8
#define NBC_Y NBC_X

#define PL_WHITE 1
#define PL_BLACK 2
#define PL_OVER 3

#define MSG_STOP 127

#define CLIENT 0
#define SERVER 1

#define GET_X_LPARAM(lp) ((int)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)HIWORD(lp))

#define WM_NETEVENT (WM_APP+1)

int Mode; //CLIENT ou SERVER
char IP_address[16] = "127.0.0.1";
WORD coord;
HINSTANCE hinst;
HANDLE hMutex;
HWND hwnd;
HWND hstb;
BOOL Connect;

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
BOOL APIENTRY Dialog1Proc(HWND, UINT, WPARAM, LPARAM);
int Play(int tab[NBC_Y][NBC_X], int x, int y, int *joueur);
void Init(int tab[NBC_Y][NBC_X]);

/******************************************************************************/
DWORD WINAPI thread_client(LPVOID lpParam)
{
WSADATA WSAData;
SOCKADDR_IN sin;
char str[256];

WSAStartup(MAKEWORD(2,0), &WSAData);

sin.sin_addr.s_addr  = inet_addr(IP_address);
sin.sin_family = AF_INET;
sin.sin_port = htons(6665);
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if(connect(sock, (SOCKADDR *)&sin, sizeof(sin)) == 0)
{
Connect = TRUE;
wsprintf(str, " Connecté : %s", IP_address);
SendMessage(hstb, SB_SETTEXT, 2, (LPARAM)str);
while(1)
{
WaitForSingleObject(hMutex, INFINITE);
int n=send(sock, (char*)&coord, sizeof(coord), 0);
ReleaseMutex(hMutex);
if(n<=0) break;

// attente des données
n=recv(sock, (char*)&coord, sizeof(coord), 0);
if(n>0)
{
int x = LOBYTE(coord);
int y = HIBYTE(coord);

if(x==MSG_STOP)
{
send(sock, (char*)&coord, sizeof(coord), 0);
break;
}
SendMessage(hwnd, WM_NETEVENT, x, y);
}
else break;
}
}

Connect = FALSE;
SendMessage(hstb, SB_SETTEXT, 2, (LPARAM)" Déconnecté");
closesocket(sock);
ReleaseMutex(hMutex);
WSACleanup();
return 0;
}

/******************************************************************************/
DWORD WINAPI thread_server(LPVOID lpParam)
{
WSADATA WSAData;
SOCKET socklisten;
SOCKADDR_IN sin;
SOCKADDR_IN cin;

WSAStartup(MAKEWORD(2,0), &WSAData);

socklisten = socket(AF_INET, SOCK_STREAM, 0);

sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_family = AF_INET;
sin.sin_port = htons(6665);

bind(socklisten, (SOCKADDR*)&sin, sizeof(sin));
listen(socklisten, 0);
int sinsize = sizeof(cin);
SendMessage(hstb, SB_SETTEXT, 2, (LPARAM)" En attente de connexion");
SOCKET sock = accept(socklisten, (SOCKADDR *)&cin, &sinsize);
if(sock == INVALID_SOCKET) return 0;

// Connexion du client...
Connect = TRUE;
SendMessage(hstb, SB_SETTEXT, 2, (LPARAM)" Connecté");

while(1)
{
int n = recv(sock, (char*)&coord, sizeof(coord), 0);
if(n>0)
{
int x = LOBYTE(coord);
int y = HIBYTE(coord);
if(x==MSG_STOP)
{
send(sock, (char*)&coord, sizeof(coord), 0);
break;
}
SendMessage(hwnd, WM_NETEVENT, x, y);
}
else break;

// Envois des données coord;
WaitForSingleObject(hMutex, INFINITE);
n=send(sock, (char*)&coord, sizeof(coord), 0);
ReleaseMutex(hMutex);
if(n<=0) break;
}

Connect = FALSE;
SendMessage(hstb, SB_SETTEXT, 2, (LPARAM)" Déconnecté");
closesocket(sock);
closesocket(socklisten);
WSACleanup();
return 0;
}

/******************************************************************************/
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static int tab[NBC_Y][NBC_X];
static int joueur;
static HANDLE hThread;
static int heightstb;

switch (uMsg)
{
case WM_CREATE:
{
int part[]= {56, 140, -1};
RECT stbRect;
hstb=CreateWindow(STATUSCLASSNAME, " Status :",
SBARS_SIZEGRIP|WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, 0);
SendMessage(hstb, SB_SETPARTS, sizeof(part)/sizeof(int), (LPARAM)part);

GetWindowRect(hstb, &stbRect);
heightstb = stbRect.bottom-stbRect.top;

joueur=PL_WHITE;
Mode = SERVER;
hMutex = CreateMutex(NULL, FALSE, NULL);
return 0;
}

case WM_COMMAND:

if(LOWORD(wParam) == IDM_STOP)
{
coord = MAKEWORD(MSG_STOP, 0);
ReleaseMutex(hMutex);
}

if(LOWORD(wParam) == IDM_NEW && Connect == FALSE)
{
ZeroMemory(tab, sizeof(tab));
Init(tab);
ReleaseMutex(hMutex);
joueur=PL_WHITE;

if(Mode==CLIENT)
{
WaitForSingleObject(hMutex, INFINITE);
SendMessage(hstb, SB_SETTEXT, 1, (LPARAM)" Client");
hThread = CreateThread(NULL, 0, thread_client, NULL, 0, NULL);
}
else
{
SendMessage(hstb, SB_SETTEXT, 1, (LPARAM)" Serveur");
hThread = CreateThread(NULL, 0, thread_server, NULL, 0, NULL);
}
InvalidateRect(hwnd, NULL, FALSE);
}

if(LOWORD(wParam) == IDM_PARAM)
DialogBox(hinst, "DIALOG1", hwnd, Dialog1Proc);

if(LOWORD(wParam) == IDM_QUIT) PostMessage(hwnd, WM_CLOSE,0,0);

if(LOWORD(wParam) == IDM_ABOUT)
MessageBox(NULL, "Othello par CGi !", "A Propos !", MB_OK);

return 0;

case WM_NETEVENT : // Jeu de l'adversaire
{
int x = wParam;
int y = lParam;

Play(tab, x, y, &joueur);
WaitForSingleObject(hMutex, INFINITE);
InvalidateRect(hwnd, NULL, FALSE);

return 0;
}

case WM_LBUTTONUP :
{
if((Connect == TRUE && Mode==SERVER && joueur==PL_BLACK) ||
(Connect == TRUE && Mode==CLIENT && joueur==PL_WHITE))
{
int x = GET_X_LPARAM(lParam)/LARG;
int y = GET_Y_LPARAM(lParam)/LARG;
if(tab[y][x]==1 || tab[y][x]==2 || x>=NBC_X || y>=NBC_Y) return 0;

int result = Play(tab, x, y, &joueur);
if(result==0) return 0;

coord = MAKEWORD(x, y);
ReleaseMutex(hMutex);
InvalidateRect(hwnd, NULL, FALSE);
}
return 0;
}

case WM_MOUSEMOVE:
{
if((Connect == TRUE && Mode==SERVER && joueur==PL_BLACK) ||
(Connect == TRUE && Mode==CLIENT && joueur==PL_WHITE))
{
static int x1, y1;

int x = GET_X_LPARAM(lParam)/LARG;
int y = GET_Y_LPARAM(lParam)/LARG;

if(tab[y1][x1]==PL_OVER) tab[y1][x1]=0;

x1=x;
y1=y;

if(x<NBC_X && y<NBC_Y && tab[y][x]==0) tab[y][x]=PL_OVER;

InvalidateRect(hwnd, NULL, FALSE);
}
return 0;
}

case WM_PAINT:
{
int i, j;
HPEN hpen, hredpen;
HDC hdc, hdcDB;
HBITMAP bmDB;
PAINTSTRUCT ps;
RECT rect;

HBRUSH hbcase = CreateSolidBrush(0x0040F040);
hpen = CreatePen(PS_SOLID, 2, 0x00000000);
hredpen = CreatePen(PS_SOLID, 2, 0x00000000);

GetClientRect(hwnd, &rect);
rect.bottom-=heightstb;

hdc = BeginPaint(hwnd, &ps);
hdcDB = CreateCompatibleDC(hdc);
bmDB = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);
SelectObject(hdcDB, bmDB);
SelectObject(hdcDB,hpen);

SelectObject(hdcDB, hbcase);

FillRect(hdcDB, &rect, hbcase);

for(j=0; j<NBC_Y; j++)
for(i=0; i<NBC_X; i++)
{
int value = tab[j][i];

Rectangle(hdcDB, i*LARG+4, j*LARG+4,
i*LARG+LARG+4, j*LARG+LARG+4);

SelectObject(hdcDB,hredpen);

if(value==PL_WHITE)
SelectObject(hdcDB, GetStockObject(WHITE_BRUSH));
if(value==PL_BLACK)
SelectObject(hdcDB, GetStockObject(BLACK_BRUSH));

if(value==PL_WHITE || value==PL_BLACK)
Ellipse(hdcDB, i*LARG+8, j*LARG+8,
i*LARG+LARG-2, j*LARG+LARG-2);
if(value==PL_OVER)
{
if(joueur==PL_WHITE)
SelectObject(hdcDB, GetStockObject(WHITE_BRUSH));
else SelectObject(hdcDB, GetStockObject(BLACK_BRUSH));

Ellipse(hdcDB, i*LARG+24, j*LARG+24,
i*LARG+LARG/2+12, j*LARG+LARG/2+12);
}

SelectObject(hdcDB, hbcase);
SelectObject(hdcDB,hpen);
}

BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcDB, 0, 0, SRCCOPY);

DeleteDC(hdcDB);
DeleteObject(bmDB);
EndPaint(hwnd, &ps);
DeleteObject(hbcase);
DeleteObject(hpen);
DeleteObject(hredpen);
return 0;
}

case WM_ERASEBKGND:
// not drawing the background.
return 0;

case WM_CLOSE :
CloseHandle(hMutex);
WaitForSingleObject(hThread, 200);
DestroyWindow(hwnd);
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;

default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}

/******************************************************************************/
BOOL APIENTRY Dialog1Proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
SetDlgItemText(hDlg, IDC_IPADDRESS1, IP_address);
if(Mode == SERVER)
{
CheckDlgButton(hDlg, IDC_RADIO1, BST_CHECKED);
EnableWindow(GetDlgItem(hDlg,IDC_IPADDRESS1),FALSE);
}
else
{
CheckDlgButton(hDlg, IDC_RADIO2, BST_CHECKED);
EnableWindow(GetDlgItem(hDlg,IDC_IPADDRESS1),TRUE);
}
return TRUE;

case WM_COMMAND:
if(LOWORD(wParam) == IDC_RADIO2)
{
EnableWindow(GetDlgItem(hDlg,IDC_IPADDRESS1),TRUE);
return TRUE;
}
if(LOWORD(wParam) == IDC_RADIO1)
{
EnableWindow(GetDlgItem(hDlg,IDC_IPADDRESS1),FALSE);
return TRUE;
}
if(LOWORD(wParam) == IDOK )
{
if(IsDlgButtonChecked(hDlg, IDC_RADIO1) == BST_CHECKED) Mode=SERVER;
else Mode=CLIENT;
GetWindowText(GetDlgItem(hDlg,IDC_IPADDRESS1), IP_address, 16);
EndDialog(hDlg,0);
return TRUE;
}
if(LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg,0);
return TRUE;
}

default:
return FALSE;
}
}

/******************************************************************************/
int Play(int tab[NBC_Y][NBC_X], int x, int y, int *joueur)
{
int valide = 0;
int advers;
if(*joueur==PL_WHITE) advers=PL_BLACK;
else advers=PL_WHITE;

int cpt=1;
while(tab[y][x+cpt]==advers && (x+cpt)<7) cpt++;
if(tab[y][x+cpt]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y][x+cpt]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y][x-cpt]==advers && (x-cpt)>0) cpt++;
if(tab[y][x-cpt]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y][x-cpt]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y+cpt][x]==advers && (y+cpt)<7) cpt++;
if(tab[y+cpt][x]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y+cpt][x]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y-cpt][x]==advers && (y-cpt)>0) cpt++;
if(tab[y-cpt][x]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y-cpt][x]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y+cpt][x+cpt]==advers && (x+cpt)<7 && (y+cpt)<7) cpt++;
if(tab[y+cpt][x+cpt]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y+cpt][x+cpt]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y+cpt][x-cpt]==advers && (x-cpt)>0 && (y+cpt)<7) cpt++;
if(tab[y+cpt][x-cpt]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y+cpt][x-cpt]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y-cpt][x+cpt]==advers && (x+cpt)<7 && (y-cpt)>0) cpt++;
if(tab[y-cpt][x+cpt]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y-cpt][x+cpt]=*joueur;
cpt--;
}
valide=1;
}

cpt=1;
while(tab[y-cpt][x-cpt]==advers && (x-cpt)>0 && (y-cpt)>0) cpt++;
if(tab[y-cpt][x-cpt]==*joueur && cpt>1)
{
while(cpt>0)
{
tab[y-cpt][x-cpt]=*joueur;
cpt--;
}
valide=1;
}

if(valide==1)
{
tab[y][x]=*joueur;
if(*joueur==PL_WHITE) *joueur=PL_BLACK;
else *joueur=PL_WHITE;
}

return valide;
}

/******************************************************************************/
void Init(int tab[NBC_Y][NBC_X])
{
tab[3][3]=PL_WHITE;
tab[3][4]=PL_BLACK;
tab[4][3]=PL_BLACK;
tab[4][4]=PL_WHITE;
}

/******************************************************************************/
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
hinst = hinstance;

wc.style = 0;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName =  "LEMENU";
wc.lpszClassName = "WinClassMain";
if(!RegisterClass(&wc)) return FALSE;

InitCommonControls();

hwnd = CreateWindow("WinClassMain", "Othello",
WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT,
LARG*NBC_X+10, LARG*NBC_Y+80, NULL, NULL, hinstance, NULL);
if (!hwnd) return FALSE;

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

À vos compilateurs.

CGi

Retour au sommaire.