是的,按鈕控件很常見,幾乎在每一個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的問題。