2019独角兽企业重金招聘Python工程师标准>>>

对话框就是一个简单的窗口,仅包含标题、文字信息和一两个特定文字的按钮。

所以我们先改造下上篇的按钮,增加类型属性,并添加几个对话框专用的特定的按钮。

// MySDL_Button.h
// SDL2 自定义部件 - 按钮#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>#ifndef MYSDL2_BUTTON_H
#define MYSDL2_BUTTON_H// 按钮状态
typedef enum en_SDL_Button_State
{BTN_STATE_NORMAL,     // 正常BTN_STATE_DOWN,       // 按下BTN_STATE_UP          // 弹起
} SDL_Button_State;// 按钮类型
typedef  enum en_SDL_Button_Type
{BT_TYPE_CUSTOM = 0, // 自定义类型,显示给定文字BT_TYPE_OK     = 1, // 其他类型,显示特定文字BT_TYPE_CANCEL = 2,BT_TYPE_YES    = 4,BT_TYPE_NO     = 8,BT_TYPE_OKCANCEL = BT_TYPE_OK | BT_TYPE_CANCEL,BT_TYPE_YESNO = BT_TYPE_YES | BT_TYPE_NO
} SDL_Button_Type;// 按钮结构
typedef struct st_SDL_Button
{SDL_Button_Type type;       // 类型int id;                     // IDint x, y, w, h;             // 尺寸char *text;                 // 文字_Bool enable;               // 是否可用SDL_Button_State state;     // 状态
} SDL_Button;// 画按钮
// 参数:pRen = 渲染器;pFont = 字体;pBtn = 按钮数组;btnNum = 按钮数量
void SDL_DrawButton(SDL_Renderer *pRen, TTF_Font *pFont, SDL_Button *pBtn, int btnNum);// 坐标是否在有效按钮上
// 参数:x,y = 坐标;pBtn = 按钮数组;btnNum = 按钮数量
// 返回值:按钮ID,或者 -1(不在有效按钮上)
int SDL_isOnButton(int x, int y, SDL_Button *pBtn, int btnNum);#endif
// MySDL_Button.h
// SDL2 自定义部件 - 按钮#include "MySDL_Texture.h"
#include "MySDL_Button.h"// 自定义按钮文字
static char *szOKCANCEL[] = {" 确定 ", " 取消 ",};
static char *szYESNO[]    = {"  是  ", "  否  "};// 坐标是否在有效按钮上
// 参数:x,y = 坐标;pBtn = 按钮数组;btnNum = 按钮数量
// 返回值:按钮ID,或者 -1(不在有效按钮上)
int SDL_isOnButton(int x, int y, SDL_Button *pBtn, int btnNum)
{for(int i = 0; i < btnNum; i++)if(pBtn[i].enable && x >= pBtn[i].x && x <= pBtn[i].x + pBtn[i].w&& y >= pBtn[i].y && y <= pBtn[i].y + pBtn[i].h)return pBtn[i].id;return -1;
}// 画按钮
// 参数:pRen = 渲染器;pFont = 字体;pBtn = 按钮数组;btnNum = 按钮数量
void SDL_DrawButton(SDL_Renderer *pRen, TTF_Font *pFont, SDL_Button *pBtn, int btnNum)
{int bgc, tc;    // 背景颜色、文字颜色Uint8 ulc, dlc; // 按钮上、下线的颜色(单R、G、B)SDL_Texture *pBGTxt, *pTextTxt; // 背景、文字纹理SDL_Rect rt;for(int i = 0; i < btnNum; i++){// 根据按钮是否可用及其状态决定底色、文字颜色if(pBtn[i].enable){tc  = 0;switch(pBtn[i].state){case BTN_STATE_NORMAL :bgc = 0xC5C5C5;ulc = 0xFF;dlc = 0;break;case BTN_STATE_DOWN :bgc = 0xA0A0A0;ulc = 0;dlc = 0xFF;break;case BTN_STATE_UP :bgc = 0xF1F1F1;ulc = 0xFF;dlc = 0;break;default :break;}}else{tc  = 0x989898;bgc = 0xF1F1F1;ulc = 0xFF;dlc = 0;}// 根据类型决定按钮上显示的文字pBGTxt = GetRGBTexture(pRen, pBtn[i].w, pBtn[i].h, bgc);switch(pBtn[i].type){case BT_TYPE_OK :pTextTxt = GetTextTexture(pRen, pFont, szOKCANCEL[0], 0);break;case BT_TYPE_CANCEL :pTextTxt = GetTextTexture(pRen, pFont, szOKCANCEL[1], 0);break;case BT_TYPE_YES :pTextTxt = GetTextTexture(pRen, pFont, szYESNO[0], 0);break;case BT_TYPE_NO :pTextTxt = GetTextTexture(pRen, pFont, szYESNO[1], 0);break;case BT_TYPE_CUSTOM :pTextTxt = GetTextTexture(pRen, pFont, pBtn[i].text, tc);break;default :break;}if(pBGTxt != NULL && pTextTxt != NULL){rt.x = pBtn[i].x;rt.y = pBtn[i].y;rt.w = pBtn[i].w;rt.h = pBtn[i].h;SDL_RenderCopy(pRen, pBGTxt, NULL, &rt);SDL_RenderCopy(pRen, pTextTxt, NULL, &rt);// 画上边线SDL_SetRenderDrawColor(pRen, ulc, ulc, ulc, SDL_ALPHA_OPAQUE);SDL_RenderDrawLine(pRen, rt.x, rt.y, rt.x + rt.w, rt.y);SDL_RenderDrawLine(pRen, rt.x, rt.y, rt.x, rt.y + rt.h);// 画下边线SDL_SetRenderDrawColor(pRen, dlc, dlc, dlc, SDL_ALPHA_OPAQUE);SDL_RenderDrawLine(pRen, rt.x + rt.w, rt.y, rt.x + rt.w, rt.y + rt.h);SDL_RenderDrawLine(pRen, rt.x, rt.y + rt.h, rt.x + rt.w, rt.y + rt.h);}if(pBGTxt != NULL)   SDL_DestroyTexture(pBGTxt);if(pTextTxt != NULL) SDL_DestroyTexture(pTextTxt);}
}

有了按钮,就可以建一个简单的窗口,只显示标题和文字内容,再加几个按钮。是窗口,当然也要自己处理消息了。

// MySDL_Dialog.h
// SDL2 自定义部件 - 对话框#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include "MySDL_Button.h"#ifndef MYSDL2_DIALOG_H
#define MYSDL2_DIALOG_H// 对话框结构
typedef struct st_SDL_Dialog
{char *title;                // 标题char *text;                 // 文字SDL_Button_Type btn_type;   // 按钮类型
} SDL_Dialog;// 显示一个简单的对话框
// 参数:pWin = 父窗口;pFont = 字体;title = 标题;text = 文字;btn_type = 按钮类型
//返回值:被点击的按钮的类型值
extern SDL_Button_Type ShowDialog(SDL_Window *pWin, TTF_Font *pFont, char *title, char *text, SDL_Button_Type btn_type);#endif
// MySDL_Dialog.c
// SDL2 自定义部件 - 对话框#include <string.h>
#include "MySDL_Texture.h"
#include "MySDL_Dialog.h"#define MARGIN 10      // 窗口边宽static void UpdateWindow(SDL_Window *pWin, SDL_Renderer *pRen, SDL_Texture **pTxt,TTF_Font *pFont, char *title, char *text, SDL_Button *pBtn, int btnNum);// 显示一个简单的对话框
// 参数:pWin = 父窗口;pFont = 字体;title = 标题;text = 文字;btn_type = 按钮类型
//返回值:被点击的按钮的类型值
extern SDL_Button_Type ShowDialog(SDL_Window *pWin, TTF_Font *pFont, char *title,char *text, SDL_Button_Type btn_type)
{int w, h;SDL_Window   *pThisWin;SDL_Renderer *pRen;SDL_Texture  *pTxt[4];  // 整体背景(标题栏、边框),文字背景,标题、文字的纹理SDL_Event    event;_Bool        bRun = 1;SDL_Button_Type ret = -1;// 通常对话框上的按钮有三种形式:1、单“确定”,2、“确定” + “取消”,3、“是” + “否”。// 默认定义为 2、“确定” + “取消”SDL_Button btn[2] ={{BT_TYPE_OK, 0, 0, 0, 0, 0, NULL, 1, BTN_STATE_NORMAL},{BT_TYPE_CANCEL, 1, 0, 0, 0, 0, NULL, 1, BTN_STATE_NORMAL}};int btnNum = (btn_type == BT_TYPE_OK ? 1 : 2);  // 控制按钮数量一个,则只有 1、单“确定”int id;// 调整为 3、“是” 和“否”if(btn_type == BT_TYPE_YESNO){btn[0].type = BT_TYPE_YES;btn[1].type = BT_TYPE_NO;}SDL_GetWindowSize(pWin, &w, &h);if(SDL_CreateWindowAndRenderer(w / 2, h / 2, SDL_WINDOW_BORDERLESS| SDL_WINDOW_INPUT_GRABBED, &pThisWin, &pRen) == -1)goto label_error;pTxt[0] = GetRGBTexture(pRen, w / 2, h / 2, 0x00FFFF);pTxt[1] = GetRGBTexture(pRen, w / 2 - 2 * MARGIN, h / 2 - 5 * MARGIN, 0xFFFFFF);pTxt[2] = GetTextTexture(pRen, pFont, title, 0);pTxt[3] = GetTextTexture(pRen, pFont, text, 0);if(NULL == pTxt[0] || NULL == pTxt[1] || NULL == pTxt[2] || NULL == pTxt[3])goto label_error;while(bRun && SDL_WaitEvent(&event)){switch(event.type){case SDL_MOUSEMOTION :      // 鼠标移动id = SDL_isOnButton(event.button.x, event.button.y, btn, btnNum);if(id >= 0) // 鼠标在某个按钮上{// 鼠标左键压下则该按钮处于凹状态,无鼠标键压下则该按钮处于凸状态if(event.motion.state == SDL_BUTTON_LMASK)btn[id].state = BTN_STATE_DOWN;elsebtn[id].state = BTN_STATE_UP;}else        // 鼠标不在按钮上,则所有按钮正常显示{for(int i = 0; i < btnNum; i++)btn[i].state = BTN_STATE_NORMAL;}UpdateWindow(pThisWin, pRen, pTxt, pFont, title, text, btn, btnNum);break;case SDL_MOUSEBUTTONDOWN :  // 鼠标键按下id = SDL_isOnButton(event.button.x, event.button.y, btn, btnNum);;if(id >= 0) // 按下某个按钮,该按钮处于凹状态{btn[id].state = BTN_STATE_DOWN;UpdateWindow(pThisWin, pRen, pTxt, pFont, title, text, btn, btnNum);}break;case SDL_MOUSEBUTTONUP :    // 鼠标按键弹起id = SDL_isOnButton(event.button.x, event.button.y, btn, btnNum);if(id >= 0) // 在某个按钮上则结束对话框,返回按钮类型{ret = btn[id].type;bRun = 0;}break;case SDL_KEYUP :// 键盘的 Esc 键 也当“取消”处理if(event.key.keysym.sym == SDLK_ESCAPE){ret = BT_TYPE_CANCEL;bRun = 0;}break;case SDL_WINDOWEVENT :      //  有窗口消息,重新计算窗口尺寸UpdateWindow(pThisWin, pRen, pTxt, pFont, title, text, btn, btnNum);break;default :break;}}label_error:if(pTxt[0] != NULL) SDL_DestroyTexture(pTxt[0]);if(pTxt[1] != NULL) SDL_DestroyTexture(pTxt[1]);if(pTxt[2] != NULL) SDL_DestroyTexture(pTxt[2]);if(pTxt[3] != NULL) SDL_DestroyTexture(pTxt[3]);if(pRen != NULL)    SDL_DestroyRenderer(pRen);if(pThisWin != NULL) SDL_DestroyWindow(pThisWin);return ret;
}// 重绘窗口
static void UpdateWindow(SDL_Window *pWin, SDL_Renderer *pRen, SDL_Texture **pTxt,TTF_Font *pFont, char *title, char *text, SDL_Button *pBtn, int btnNum)
{SDL_Rect rt;int w, h;SDL_GetWindowSize(pWin, &w, &h);SDL_RenderClear(pRen);// 整体背景(标题栏、边框)SDL_RenderCopy(pRen, pTxt[0], NULL, NULL);//文字背景rt.x = MARGIN;rt.y = 4 * MARGIN;rt.w = w - 2 * MARGIN;rt.h = h - 5 * MARGIN;SDL_RenderCopy(pRen, pTxt[1], NULL, &rt);// 标题rt.x = MARGIN;rt.y = MARGIN / 2;rt.w = MARGIN * strlen(title);rt.h = 3 * MARGIN;SDL_RenderCopy(pRen, pTxt[2], NULL, &rt);// 文字rt.y = 6 * MARGIN;rt.w = MARGIN * strlen(text);rt.h = 3 * MARGIN;SDL_RenderCopy(pRen, pTxt[3], NULL, &rt);// 按钮if(btnNum == 1){pBtn[0].x = 3 * w / 4;pBtn[0].y = 3 * h / 4;}else{pBtn[0].x = w / 4;pBtn[1].x = 3 * w / 4;pBtn[0].y = pBtn[1].y = 3 * h / 4;}pBtn[1].w = pBtn[0].w = w / 6;pBtn[1].h = pBtn[0].h = h / 6;SDL_DrawButton(pRen, pFont, pBtn, btnNum);SDL_RenderPresent(pRen);
}

然后就可以在五子棋里测试了,给“悔棋”按钮加上显示对话框的功能

// Five.c
// SDL2 五子棋//#define _DEBUG_#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_mixer.h>
#include <stdio.h>
#include <string.h>
#include "MySDL_Texture.h"
#include "MySDL_Button.h"
#include "MySDL_Dialog.h"
#include "FiveData.h"// 资源文件
int  BackColor      = 0xFFFFFF; // 棋子图片的背景色
char *ImgFileName[] =
{"Resource/BackGround.jpg",  // 棋盘背景图文件"Resource/BlackPiece.jpg",  // 黑棋子图文件"Resource/WhitePiece.jpg"   // 白棋子图文件
};
char SoundFileName[] = "Resource/Stone.mp3";        // 落子音效文件
char FontFileName[]  = "C:/Windows/Fonts/msyh.ttf"; // Windows 下字体文件// 字符串常量
char szWinTitle[]  = "SDL2 五子棋";
char *szWho[]      = {"黑方", "白方"};
char *szGameTips[] = {"第 %d 手,轮到 %s 落子", "共 %d 手,%s 取得本局胜利"};_Bool OnKeyUp(int x, int y, int nSpacing);
void DrawBoard(SDL_Renderer *pRen, int nSpacing, int c);
void DrawPieces(SDL_Renderer *pRen, int nSpacing, SDL_Texture **pImgTxt);
void PrintString(SDL_Renderer *pRen, int nSpacing, TTF_Font *pFont, char *text, int c);
static void UpdateWindow(SDL_Window *pWin, SDL_Renderer *pRen, int nSpacing,TTF_Font *pFont, SDL_Texture **pImgTxt, SDL_Button *pBtn, int n);#undef main
int main(int argc, char **argv)
{int WinW = 640, WinH = 480; // 屏幕尺寸int nSpacing;               // 棋盘线距SDL_Window   *pWin;         // 主窗口SDL_Renderer *pRen;         // 主窗口渲染器SDL_Texture  *pImgTxt[3];   // 棋盘背景、黑白棋子图纹理TTF_Font     *pFont;        // 提示文字字体Mix_Music    *pMusic;       // 音效SDL_Event    event;         // 事件_Bool        bRun = 1;      // 持续等待事件控制循环标识// 按钮SDL_Button btn[] ={{BT_TYPE_CUSTOM, 0, 0, 0, 0, 0, " 新局 ", 0, BTN_STATE_NORMAL},{BT_TYPE_CUSTOM, 1, 0, 0, 0, 0, " 悔棋 ", 0, BTN_STATE_NORMAL},};int btnNum = sizeof(btn) / sizeof(SDL_Button);int id;// 初始化:SDL2、SDL_image(jpg)、SDL_ttf、SDL_mixer(mp3)if(SDL_Init(SDL_INIT_EVERYTHING) == -1 || IMG_Init(IMG_INIT_JPG) == -1 || TTF_Init() == -1|| Mix_Init(MIX_INIT_MP3) == -1 || Mix_OpenAudio(MIX_DEFAULT_FREQUENCY,MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096) == -1){
#ifdef _DEBUG_fprintf(stderr, "1 %s", SDL_GetError());
#endifreturn 1;}// 创建主窗口及其渲染器if(SDL_CreateWindowAndRenderer(WinW, WinH, SDL_WINDOW_FULLSCREEN, &pWin, &pRen) == -1){
#ifdef _DEBUG_fprintf(stderr, "2 %s", SDL_GetError());
#endifgoto label_error;}SDL_SetWindowTitle(pWin, szWinTitle);// 加载图片文件if(NULL == (pImgTxt[0] = GetImageTexture(pRen, ImgFileName[0], 0, 0))|| NULL == (pImgTxt[1] = GetImageTexture(pRen, ImgFileName[1], 1, BackColor))|| NULL == (pImgTxt[2] = GetImageTexture(pRen, ImgFileName[2], 1, BackColor))){
#ifdef _DEBUG_fprintf(stderr, "3 %s", IMG_GetError());
#endifgoto label_error;}// 加载字体文件if(NULL == (pFont = TTF_OpenFont(FontFileName, 20))){
#ifdef _DEBUG_fprintf(stderr, "4 %s", TTF_GetError());
#endifgoto label_error;}// 加载声音文件if(NULL == (pMusic = Mix_LoadMUS(SoundFileName))){
#ifdef _DEBUG_fprintf(stderr, "5 %s", Mix_GetError());
#endifgoto label_error;}Five_ResetData();while(bRun && SDL_WaitEvent(&event)){switch(event.type){case SDL_MOUSEMOTION :      // 鼠标移动id = SDL_isOnButton(event.button.x, event.button.y, btn, btnNum);// 鼠标在某个按钮上if(id >= 0){// 鼠标左键压下则该按钮处于凹状态,无鼠标键压下则该按钮处于凸状态if(event.motion.state == SDL_BUTTON_LMASK)btn[id].state = BTN_STATE_DOWN;elsebtn[id].state = BTN_STATE_UP;}// 鼠标不在按钮上else{// 所有按钮正常显示for(int i = 0; i < btnNum; i++)btn[i].state = BTN_STATE_NORMAL;}UpdateWindow(pWin, pRen, nSpacing, pFont, pImgTxt, btn, btnNum);break;case SDL_MOUSEBUTTONDOWN :  // 鼠标键按下id = SDL_isOnButton(event.button.x, event.button.y, btn, btnNum);;// 按下某个按钮,该按钮处于凹状态if(id >= 0){btn[id].state = BTN_STATE_DOWN;UpdateWindow(pWin, pRen, nSpacing, pFont, pImgTxt, btn, btnNum);}break;case SDL_MOUSEBUTTONUP :    // 鼠标按键弹起id = SDL_isOnButton(event.button.x, event.button.y, btn, 2);// 在某个按钮上则响应功能,在棋盘则检测落子// 新局if(id == 0){btn[0].enable = 0;btn[1].enable = 0;Five_ResetData();}// 悔棋else if(id == 1){id = ShowDialog(pWin, pFont, "悔棋", "要悔棋吗?", BT_TYPE_YESNO);if(id == BT_TYPE_YES)ShowDialog(pWin, pFont, "对不起", "还没实现悔棋功能呢", BT_TYPE_OKCANCEL);else if(id == BT_TYPE_NO)ShowDialog(pWin, pFont, "还好", "你没点是", BT_TYPE_OK);}// 有效落子else if(id < 0 && g_iWho != NONE && OnKeyUp(event.button.x, event.button.y, nSpacing)){Mix_PlayMusic(pMusic, 0);btn[0].enable = 1;btn[1].enable = 1;if(Five_isFive())g_iWho = NONE;}UpdateWindow(pWin, pRen, nSpacing, pFont, pImgTxt, btn, btnNum);break;case SDL_WINDOWEVENT :      //  有窗口消息,重新计算窗口尺寸SDL_GetWindowSize(pWin, &WinW, &WinH);nSpacing = SDL_min(WinW, WinH) / (MAX_LINES + 2);UpdateWindow(pWin, pRen, nSpacing, pFont, pImgTxt, btn, btnNum);break;case SDL_QUIT :bRun = 0;break;default :break;}}label_error:// 清理if(pImgTxt[0] != NULL) SDL_DestroyTexture(pImgTxt[0]);if(pImgTxt[1] != NULL) SDL_DestroyTexture(pImgTxt[1]);if(pImgTxt[2] != NULL) SDL_DestroyTexture(pImgTxt[2]);if(pRen != NULL)   SDL_DestroyRenderer(pRen);if(pWin != NULL)   SDL_DestroyWindow(pWin);if(pFont != NULL)  TTF_CloseFont(pFont);if(pMusic != NULL) Mix_FreeMusic(pMusic);Mix_CloseAudio();TTF_Quit();IMG_Quit();SDL_Quit();return 0;
}// 重绘窗口
static void UpdateWindow(SDL_Window *pWin, SDL_Renderer *pRen, int nSpacing,TTF_Font *pFont, SDL_Texture **pImgTxt, SDL_Button *pBtn, int btnNum)
{char szString[256];SDL_RenderClear(pRen);SDL_RenderCopy(pRen, pImgTxt[0], NULL, NULL);DrawBoard(pRen, nSpacing, 0);DrawPieces(pRen, nSpacing, pImgTxt);sprintf(szString, szGameTips[g_iWho == NONE],g_nHands + (g_iWho != NONE), szWho[(g_nHands + (g_iWho == NONE)) % 2]);PrintString(pRen, nSpacing, pFont, szString, 0);pBtn[1].x = pBtn[0].x = nSpacing * (MAX_LINES + 1);pBtn[0].y = nSpacing;pBtn[1].y = nSpacing * 3;pBtn[1].w = pBtn[0].w = nSpacing * 2;pBtn[1].h = pBtn[0].h = nSpacing;SDL_DrawButton(pRen, pFont, pBtn, btnNum);SDL_RenderPresent(pRen);
}// 响应落子按键
// 参数:(x,y) = 被点击的窗口坐标;nSpacing = 棋盘线距
_Bool OnKeyUp(int x, int y, int nSpacing)
{// 计算落点棋盘坐标int m = (x - 0.5 * nSpacing) / nSpacing;int n = (y - 0.5 * nSpacing) / nSpacing;// 处理有效落点if(m >= 0 && m < MAX_LINES && n >= 0 && n < MAX_LINES && g_iBoard[m][n] == NONE){Five_AddPiece(m, n, g_iWho);return 1;}return 0;
}// 画圆(SDL2 没有画圆的函数,先用矩形框代替吧)
// 参数:pRen = 渲染器;(x,y) = 圆心坐标;r = 半径;c = 填充色
void FillCircle(SDL_Renderer *pRen, int x, int y, int r, int c)
{SDL_Rect rt = {x - r, y - r, 2 * r, 2 * r};SDL_SetRenderDrawColor(pRen, c >> 16, (c >> 8) & 0xFF, c & 0xFF, SDL_ALPHA_OPAQUE);SDL_RenderFillRect(pRen, &rt);
}// 画棋盘
// 参数:pRen = 渲染器;nSpacing = 棋盘线距;c = 线及星颜色
void DrawBoard(SDL_Renderer *pRen, int nSpacing, int c)
{int r, x, y, z;// 棋盘线SDL_SetRenderDrawColor(pRen, c >> 16, (c >> 8) & 0xFF, c & 0xFF, SDL_ALPHA_OPAQUE);for(int i = 1; i <= MAX_LINES; i++){SDL_RenderDrawLine(pRen, nSpacing, i * nSpacing, MAX_LINES * nSpacing, i * nSpacing);SDL_RenderDrawLine(pRen, i * nSpacing, nSpacing, i * nSpacing, MAX_LINES * nSpacing);}// 星位r = nSpacing * 0.2;                 // 星半径x = nSpacing * 4;                   // 第四线y = nSpacing * (MAX_LINES + 1) / 2; // 中线z = nSpacing * (MAX_LINES - 3);     // 倒数第四线FillCircle(pRen, x, x, r, c);FillCircle(pRen, y, x, r, c);FillCircle(pRen, z, x, r, c);FillCircle(pRen, x, y, r, c);FillCircle(pRen, y, y, r, c);FillCircle(pRen, z, y, r, c);FillCircle(pRen, x, z, r, c);FillCircle(pRen, y, z, r, c);FillCircle(pRen, z, z, r, c);
}// 画棋子
// 参数:pRen = 渲染器;nSpacing = 棋盘线距;pImgTxt = 棋子纹理
void DrawPieces(SDL_Renderer *pRen, int nSpacing, SDL_Texture **pImgTxt)
{int r = 0.4 * nSpacing; // 棋子半径SDL_Rect rt = {0, 0, 2 * r, 2 * r};if(g_nHands <= 0)return;for(int i = 0; i < MAX_LINES; i++){for(int j = 0; j < MAX_LINES; j++){rt.x = (i + 1) * nSpacing - r;rt.y = (j + 1) * nSpacing - r;if(g_iBoard[i][j] == BLACK)SDL_RenderCopy(pRen, pImgTxt[1], NULL, &rt);else if(g_iBoard[i][j] == WHITE)SDL_RenderCopy(pRen, pImgTxt[2], NULL, &rt);}}
}// 提示文字
// 参数:pRen = 渲染器;nSpacing = 棋盘线距;pFont = 字体;text = 文字内容;c = 文字颜色
void PrintString(SDL_Renderer *pRen, int nSpacing, TTF_Font *pFont, char *text, int c)
{SDL_Texture *pTextTxt;SDL_Rect rt;rt.x = nSpacing;rt.y = nSpacing * (MAX_LINES + 1);rt.w = nSpacing * strlen(text) / 4; // 这个 4 和字体大小有关rt.h = nSpacing;if((pTextTxt = GetTextTexture(pRen, pFont, text, c)) != NULL){SDL_RenderCopy(pRen, pTextTxt, NULL, &rt);SDL_DestroyTexture(pTextTxt);}
}

为了统一,把获得纹理的模块也稍微改了下格式

// MySDL_Texture.h
// SDL2 公共函数 - 取得 RGB、图片、文字的纹理#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>#ifndef MYSDL2_TEXTURE_H
#define MYSDL2_TEXTURE_H// 取得 RGB 纹理
// 参数:pRen = 渲染器;w, h = 宽、高;c = 颜色
// 返回值:纹理指针
SDL_Texture *GetRGBTexture(SDL_Renderer *pRen, int w, int h, int c);// 取得图片文件纹理
// 参数:pRen = 渲染器;FileName = 图片文件名;bTrn = 是否透明处理;c = 背景色
// 返回值:纹理指针
SDL_Texture *GetImageTexture(SDL_Renderer *pRen, char *FileName, _Bool bTrn, int c);// 取得文字纹理
// 参数:pRen = 渲染器;pFont = 字体;text = 文字内容;c = 文字颜色
// 返回值:纹理指针
SDL_Texture *GetTextTexture(SDL_Renderer *pRen, TTF_Font *pFont, char *text, int c);#endif
// MySDL_Texture.c
// SDL2 公共函数 - 取得 RGB、图片、文字的纹理#include "MySDL_Texture.h"// 取得 RGB 纹理
// 参数:pRen = 渲染器;w, h = 宽、高;c = 颜色
// 返回值:纹理指针
SDL_Texture *GetRGBTexture(SDL_Renderer *pRen, int w, int h, int c)
{SDL_Texture *pTexture;SDL_Surface *pSurface;if((pSurface = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0)) == NULL)return NULL;SDL_FillRect(pSurface, NULL, c);pTexture = SDL_CreateTextureFromSurface(pRen, pSurface);SDL_FreeSurface(pSurface);return pTexture;
}// 取得图片文件纹理
// 参数:pRen = 渲染器;FileName = 图片文件名;bTrn = 是否透明处理;c = 背景色
// 返回值:纹理指针
SDL_Texture *GetImageTexture(SDL_Renderer *pRen, char *FileName, _Bool bTrn, int c)
{SDL_Texture *pTexture;SDL_Surface *pSurface;if((pSurface = IMG_Load(FileName)) == NULL)return NULL;if(bTrn)SDL_SetColorKey(pSurface, 1,SDL_MapRGB(pSurface->format, c>>16, (c>>8)&0xFF, c&0xFF));pTexture = SDL_CreateTextureFromSurface(pRen, pSurface);SDL_FreeSurface(pSurface);return pTexture;
}// 取得文字纹理
// 参数:pRen = 渲染器;pFont = 字体;text = 文字内容;c = 文字颜色
// 返回值:纹理指针
SDL_Texture *GetTextTexture(SDL_Renderer *pRen, TTF_Font *pFont, char *text, int c)
{SDL_Texture *pTexture;SDL_Surface *pSurface;SDL_Color color = {c>>16, (c>>8)&0xFF, c&0xFF};if((pSurface = TTF_RenderUTF8_Blended(pFont, text, color)) == NULL)return NULL;pTexture = SDL_CreateTextureFromSurface(pRen, pSurface);SDL_FreeSurface(pSurface);return pTexture;
}

把 Makefile 也贴出来吧

SourceFile = Five.c FiveData.c MySDL_Dialog.c MySDL_Button.c MySDL_Texture.c
Library    = -lSDL2 -lSDL2main -lSDL2_image -lSDL2_ttf -lSDL2_mixerALL: $(SourceFile) Makefilegcc -mwindows -o Five $(SourceFile) $(Library)

数据处理部分、图片文件、声音和前面一样。

另外,这个办法在安卓下无效,原因不明。

转载于:https://my.oschina.net/u/580100/blog/614964

SDL2 自建对话框相关推荐

  1. Java--创建窗口和程序片

    Java  创建窗口和程序片 在Java 1.0中,图形用户接口(GUI)库最初的设计目标是让程序员构建一个通用的GUI,使其在所有平台上都能正常显示. 但遗憾的是,这个目标并未达到.事实上,Java ...

  2. Android Pie提供了自适应供电、神经网络API 1.1等新特性

    Google发布了Android Oreo的后继版本Android Pie.Android Pie提供了"刘海"屏显示支持(Display cutout).神经网络API 1.1. ...

  3. JavaFX 的 UI 控件集 ControlsFX

    出处:http://www.oschina.net/p/controlsfx JavaFX 的 UI 控件集 ControlsFX ControlsFX 开源项目旨在为 JavaFX 开发提供更多的 ...

  4. VS2010 对Excel读写操作

    VS2010对Excel读写操作 一.开发环境 编程环境 VS2010 office版本 office 2010 注意 :这里office版本号不一定非得和vs版本号一致. 二.基本实现功能 基本实现 ...

  5. VS2010 对Excel读写操作

    https://blog.csdn.net/ywx123_/article/details/77074038 VS2010对Excel读写操作 一.开发环境 编程环境 VS2010 office版本 ...

  6. vs2013我建了两个对话框 选择主对话框_VS/MFC编程教程:如何创建对话框模板和修改对话框属性...

    创建对话框主要分两大步,第一,创建对话框资源,主要包括创建新的对话框模板.设置对话框属性和为对话框添加各种控件:第二,生成对话框类,主要包括新建对话框类.添加控件变量和控件的消息处理函数等.在本节中先 ...

  7. android按任意建关闭对话框,Android: 创建一个AlertDialog对话框,必须按确定或取消按钮才能关闭对话框,禁止按[返回键]或[搜索键]关闭...

    AlertDialog.Builder builder = new Builder(this); builder.create().show(); 这样显示出来的对话框,当用户按返回键或搜索键时,这个 ...

  8. MFC-创建模态对话框和非模态对话框的方法

    注意:以下实例中创建模态对话框时没有用create(id号)绑定资源id,而非模态对话框中要用create(id号)绑定对话框资源id. 在MFC中对话框有两种形式,一个是模态对话框(model di ...

  9. windows form窗体应用程序,建一个记事本参考代码,重点是打开,保存,另存为...

    //当点击打开的时候private string files; //建一个成员变量,用来存储打开的路径private void 打开OToolStripMenuItem_Click(object se ...

最新文章

  1. 两个函数式解决大数相加的方法
  2. python自学教材-python零基础自学教材
  3. php去除中间空格,php删除字符串中间空格的方法
  4. 如何制作印章_电子公章怎么制作
  5. iOS底层探索(二) - 写给小白看的Clang编译过程原理
  6. android对象缓存,Android简单实现 缓存数据
  7. Sort HDU5884(二分+多叉哈夫曼树)
  8. 如何利用docker 构建golang线上部署环境
  9. AIR文件上传与文件断点续传方式下载
  10. 如何在 Mac 上的“查找”中抹掉设备?
  11. 三向合并和 Git 的合并策略,手把手教你Git 合并
  12. “威金(Worm.Viking)”病毒特点-专杀及_desktop.ini删除
  13. 安卓搞机教程--修改设置里 添加选项 添加文字 修改图标 修改版本号等等 实例解析
  14. python爬取别人qq空间相册_用python爬取QQ空间
  15. HTML5期末大作业:北京旅游网页设计制作(1页) 简单静态HTML网页作品 我的旅游网页作业成品 学生旅游网站模板
  16. kaggle新手入门第一篇——Titanic
  17. 数据结构(本科学习)
  18. scala的futue和promise
  19. 前端开发实习生-实习日志
  20. 台式计算机是第几代,台式机内存条怎么辨别是几代的?

热门文章

  1. Android 动画(四)---逐帧动画
  2. JQuery 源码解析资料
  3. Android-View点击事件短时间重复点击的过滤
  4. Spring框架—SpringBean加载过程
  5. 常见索引结构—FST
  6. “数据中台”是什么?
  7. linux动态链接库
  8. Shell脚本编写及常见面试题
  9. SQL Server 大数据搬迁之文件组备份还原实战
  10. SU Demos-05Sorting Traces-03susorty