是的,按钮控件很常见,几乎在每一个Windows窗体内都能找到它的身影。SDL作为一套“一套开放源代码的跨平台多媒体开发库”,自然可以实现按钮。而按钮实现的重点,就是SDL的鼠标响应事件。
SDL的鼠标事件包括鼠标移动事件、按下鼠标键、松开鼠标键,和键盘一样,当你移动鼠标时发生鼠标移动事件,按下一个鼠标键,比如说左键时,发生按下鼠标键事件,松开鼠标键时会发生松开鼠标键事件。可以通过
SDL_PollEvent(&Event);
来把上一个事件从事件队列中取出。接下来可以进行判断,如果其type为SDL_MOUSEBUTTONDOWN则为鼠标按下,这时可以进行按下按钮后该做的事情,并把按钮的图片更新为按下后的样式。如果type为SDL_MOUSEBUTTONUP则为鼠标松开,则把按钮图片样式恢复未按下的情况。SDL_MOUSEMOTION表示鼠标在窗口表面移动,这时候可以把按钮更新到被指向的样式。当然,以上的一切更新,都是在鼠标的xy坐标位于按钮上才进行的。
懂了鼠标事件,SDL实现按钮就很容易了。下面我直接贴上源代码,如果要背景图片和按钮图片可以点击下载。这个程序还有一些缺陷,主要是按钮图片有渐变色,去背景不彻底导致不美观。大家可以自己修改按钮图片。当然修改时要把程序中原来的图片宽、高的信息修改。
1 #include <iostream> 2 #include <cstdlib> 3 #include <SDL2/SDL.h> 4 #include <SDL2/SDL_image.h> 5 const Uint32 H=650,W=1000; 6 const Uint32 FPS=20; 7 const char* BuFile[]={"B1.png","B2.png","B3.png"}; 8 SDL_Window *MainWin=NULL; 9 SDL_Surface *BackGround=NULL,*ButtonSur=NULL; 10 SDL_Renderer *Render=NULL; 11 SDL_Texture *BackText=NULL,*ButtonText=NULL; 12 SDL_Rect ButtRect={0,0,64,64}; 13 SDL_Event Mouse; 14 using namespace std; 15 16 bool System_Init(); 17 bool DrawBackGround(); 18 bool UpdateButton(Uint32); 19 bool isOnButton(Uint32,Uint32); 20 void halt(); 21 void Destroy(); 22 23 int main(int argc,char *argv[]){ 24 if (!System_Init()) halt(); 25 if (!DrawBackGround()) halt(); 26 bool quit=false; 27 Uint32 _FPS_Timer=0,Buttonnow=0; 28 if (!UpdateButton(0)) halt(); 29 while (!quit){ 30 while (SDL_PollEvent(&Mouse)){ 31 switch (Mouse.type){ 32 case SDL_QUIT: 33 quit=true; 34 break; 35 case SDL_MOUSEBUTTONDOWN: 36 if (Mouse.button.button==SDL_BUTTON_LEFT) 37 if (isOnButton(Mouse.button.x,Mouse.button.y)) 38 if (Buttonnow!=2){ 39 if (!UpdateButton(2)) halt(); 40 Buttonnow=2; 41 } 42 break; 43 case SDL_MOUSEMOTION: 44 if (isOnButton(Mouse.button.x,Mouse.button.y)){ 45 if (Buttonnow!=1){ 46 if (!UpdateButton(1)) halt(); 47 Buttonnow=1; 48 }}else 49 if (Buttonnow!=0){ 50 if (!UpdateButton(0)) halt(); 51 Buttonnow=0; 52 } 53 break; 54 case SDL_MOUSEBUTTONUP: 55 if (isOnButton(Mouse.button.x,Mouse.button.y)){ 56 if (Buttonnow!=1){ 57 if (!UpdateButton(1)) halt(); 58 Buttonnow=1; 59 }}else 60 if (Buttonnow!=0){ 61 if (!UpdateButton(0)) halt(); 62 Buttonnow=0; 63 } 64 } 65 } 66 if(SDL_GetTicks()-_FPS_Timer<1000/FPS) 67 SDL_Delay(1000/FPS-SDL_GetTicks()+_FPS_Timer); 68 _FPS_Timer=SDL_GetTicks(); 69 } 70 return 0; 71 } 72 void halt(){ 73 cerr<<SDL_GetError()<<endl; 74 Destroy(); 75 exit(-1); 76 } 77 bool System_Init(){ 78 if (SDL_Init(SDL_INIT_VIDEO)==-1) return false; 79 if (IMG_Init(IMG_INIT_PNG)==-1) return false; 80 MainWin=SDL_CreateWindow("Button Test",540,270,W,H,SDL_WINDOW_SHOWN); 81 if (MainWin==NULL) return false; 82 Render=SDL_CreateRenderer(MainWin,-1,SDL_RENDERER_ACCELERATED); 83 if (Render==NULL) return false; 84 return true; 85 } 86 bool DrawBackGround(){ 87 BackGround=IMG_Load("BG.png"); 88 if (BackGround==NULL) return false; 89 BackText=SDL_CreateTextureFromSurface(Render,BackGround); 90 if (BackText==NULL) return false; 91 SDL_RenderClear(Render); 92 SDL_RenderCopy(Render,BackText,NULL,NULL); 93 SDL_RenderPresent(Render); 94 return true; 95 } 96 void Destroy(){ 97 SDL_FreeSurface(BackGround); 98 SDL_DestroyWindow(MainWin); 99 SDL_DestroyRenderer(Render); 100 SDL_DestroyTexture(BackText); 101 IMG_Quit(); 102 SDL_Quit(); 103 } 104 bool UpdateButton(Uint32 ButtonMode){ 105 DrawBackGround(); 106 const char* OpenButton=BuFile[ButtonMode]; 107 ButtonSur=IMG_Load(OpenButton); 108 Uint32 color_key=SDL_MapRGB(ButtonSur->format,255,255,255); 109 SDL_SetColorKey(ButtonSur,SDL_TRUE,color_key); 110 if (ButtonSur==NULL) return false; 111 ButtonText=SDL_CreateTextureFromSurface(Render,ButtonSur); 112 if (BackText==NULL) return false; 113 SDL_RenderCopy(Render,ButtonText,NULL,&ButtRect); 114 SDL_RenderPresent(Render); 115 return true; 116 } 117 bool isOnButton(Uint32 x,Uint32 y){ 118 if (x>=0&&x<=64) 119 if (y>=0&&y<=64) return true; 120 return false; 121 }
Bug Fix(2015-3-13 18:02):解决了鼠标提起那个时候按钮不能切换到状态0的问题。