Pada SDL versi 1.2, program yang dibuat dengan SDL hanya bisa menampilkan satu window saja. Ini berbeda dengan SDL 2.0 yang menambahkan banyak fitur baru. Salah satu fitur tersebut adalah satu program yang bisa menggunakan beberapa window.
Untuk membuat window kita bisa menggunakan fungsi SDL_CreateWindow. Selain itu, kita perlu variabel bertipe SDL_Window untuk menyimpan informasi yang dikembalikan oleh fungsi SDL_CreateWindow.Kali ini, kita akan menggunakan SDL_Renderer. Kita akan membuat fungsi khusus yang berisi pembuatan windows dan renderernya. Karena setiap window memiliki informasinya masing-masing, sebaiknya kita membuat struct yang menyimpan informasi-informasi terkait dengan window-window tersebut. Header, struct, dan variabel lain yang akan kita perlukan dalam program bisa kalian lihat di bawah ini.
#include <SDL2/SDL.h>
#define TOTAL_WINDOWS 3
#define salah 0
#define benar 1
struct info_window{
SDL_Window *mwindow;
SDL_Renderer *mrenderer;
int idwindow;
int tinggi;
int lebar;
int tutup;
int mKeyboardfocus;
int mMinimized;
int mMousefocus;
}windowku[TOTAL_WINDOWS];
Karena kita akan membuat beberapa window, kita juga perlu menyediakan function untuk membuat window supaya program menjadi lebih singkat.
int buat_window(const char *nama, info_window *twindow){
twindow->mwindow=SDL_CreateWindow(nama, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if( twindow->mwindow == NULL ){
printf( "Error : %s", SDL_GetError() );
return 0;
}else{
twindow->mrenderer = SDL_CreateRenderer(twindow->mwindow, -1, SDL_RENDERER_ACCELERATED);
if(twindow->mrenderer!=NULL){
SDL_SetRenderDrawColor(twindow->mrenderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_GetWindowID(twindow->mwindow);
}else return 0;
}
return 1;
}
Selain function untuk membuat window, kita juga perlu function untuk menghandle event dari setiap window. Event khusus untuk window diperlakukan berbeda dengan jenis event lainnya. Event untuk window (seperti saat window ditutup atau saat window mendapatkan fokus) memerlukan penanganan khusus karena event
window memberikan nilai yang sama pada "type" yang
merupakan anggota dari SDL_Event. Jenis event untuk windows lebih
spesifiknya disimpan dalam "window.event". Selain itu kita bisa mengetahui window yang mendapatkan event dari nilai "window.windowID". Beberapa event khusus untuk window dalam SDL bisa kalian lihat di bawah ini.
- SDL_WINDOWEVENT_SHOWN
- SDL_WINDOWEVENT_HIDDEN
- SDL_WINDOWEVENT_EXPOSED
- SDL_WINDOWEVENT_MOVED
- SDL_WINDOWEVENT_RESIZED
- SDL_WINDOWEVENT_SIZE_CHANGED
- SDL_WINDOWEVENT_MINIMIZED
- SDL_WINDOWEVENT_MAXIMIZED
- SDL_WINDOWEVENT_RESTORED
- SDL_WINDOWEVENT_ENTER
- SDL_WINDOWEVENT_LEAVE
- SDL_WINDOWEVENT_FOCUS_GAINED
- SDL_WINDOWEVENT_FOCUS_LOST
- SDL_WINDOWEVENT_CLOSE
- SDL_WINDOWEVENT_TAKE_FOCUS
- SDL_WINDOWEVENT_HIT_TEST
Berikut ini adalah contoh function untuk menghandle event khusus window saat "type" bernilai SDL_WINDOWEVENT.
int event_window(SDL_Event *e, info_window *twindow){
if( e->window.windowID == twindow->idwindow ){
switch( e->window.event ){
//window terlihat
case SDL_WINDOWEVENT_SHOWN:
twindow->tutup=salah;
break;
//Window menghilang
case SDL_WINDOWEVENT_HIDDEN:
twindow->tutup=benar;
break;
//Window berubah ukuran
case SDL_WINDOWEVENT_SIZE_CHANGED:
twindow->lebar = e->window.data1;
twindow->tinggi = e->window.data2;
SDL_RenderPresent( twindow->mrenderer );
break;
case SDL_WINDOWEVENT_EXPOSED:
SDL_RenderPresent( twindow->mrenderer );
break;
//Mouse enter
case SDL_WINDOWEVENT_ENTER:
twindow->mMousefocus=benar;
break;
//Mouse exit
case SDL_WINDOWEVENT_LEAVE:
twindow->mMousefocus=salah;
break;
//Keyboard focus gained
case SDL_WINDOWEVENT_FOCUS_GAINED:
twindow->mKeyboardfocus=benar;
break;
//Keyboard focus lost
case SDL_WINDOWEVENT_FOCUS_LOST:
twindow->mKeyboardfocus=salah;
break;
//Window minimized
case SDL_WINDOWEVENT_MINIMIZED:
twindow->mMinimized=benar;
break;
//Window maximized
case SDL_WINDOWEVENT_MAXIMIZED:
twindow->mMinimized=salah;
break;
//Window restored
case SDL_WINDOWEVENT_RESTORED:
twindow->mMinimized=salah;
break;
//Window ditutup
case SDL_WINDOWEVENT_CLOSE:
SDL_HideWindow( twindow->mwindow);
break;
}
}
return 0;
}
Fungsi utama dari program berisi beberapa loop karena kita menggunakan beberapa window. Loop yang pertama adalah loop untuk membuat window baru yang jumlahnya sesuai dengan nilai TOTAL_WINDOWS. Jika windows berhasil dibuat, maka loop berikutnya adalah loop untuk menghandle event yang akan dieksekusi hingga semua window ditutup.
int main(int argc, char* args[]){
SDL_Event evt;
int hasil;
if( SDL_Init( SDL_INIT_VIDEO ) < 0){
printf( "Error: %s\n", SDL_GetError() );
}else{
for(int i=0;i<TOTAL_WINDOWS;i++){
hasil+=buat_window("SDL_test", &windowku[i]);
}
if(hasil>=TOTAL_WINDOWS){
int berhenti=salah;
while(berhenti==salah){
while(SDL_PollEvent(&evt)){
switch(evt.type){
case SDL_WINDOWEVENT :
for( int i = 0; i < TOTAL_WINDOWS; i++ ){
event_window(&evt, &windowku[i]);
}
break;
case SDL_KEYDOWN:
switch(evt.key.keysym.sym){
case SDLK_1:
SDL_ShowWindow(windowku[0].mwindow);
SDL_RaiseWindow(windowku[0].mwindow);
break;
case SDLK_2:
SDL_ShowWindow(windowku[1].mwindow);
SDL_RaiseWindow(windowku[1].mwindow);
break;
case SDLK_3:
SDL_ShowWindow(windowku[2].mwindow);
SDL_RaiseWindow(windowku[2].mwindow);
break;
}
}
}
for(int i=0;i<TOTAL_WINDOWS;i++){
SDL_RenderClear(windowku[i].mrenderer);
SDL_RenderPresent(windowku[i].mrenderer);
}
int semua_tutup=benar;
for(int i=0;i<TOTAL_WINDOWS;i++){
if(windowku[i].tutup==salah){
semua_tutup=salah;
break;
}
}
if(semua_tutup==benar)berhenti=benar;
}
}
}
for(int i=0;i<3;i++)SDL_DestroyWindow( windowku[i].mwindow );
SDL_Quit();
return 0;
}
Pada saat program baru dijalankan, program seharusnya akan menampilkan beberapa window sesuai nilai yang diberikan pada TOTAL_WINDOWS. Program akan berhenti saat semua window "ditutup". Setelah semua window ditutup, kita perlu menggunakan SDL_DestroyWindow untuk membersihkan memori yang digunakan setiap window karena window belum benar-benar ditutup setelah window disembunyikan.
Program utuhnya bisa kalian lihat di bawah ini.
#include <SDL2/SDL.h>
#define TOTAL_WINDOWS 3
#define salah 0
#define benar 1
struct info_window{
SDL_Window *mwindow;
SDL_Renderer *mrenderer;
int idwindow;
int tinggi;
int lebar;
int tutup;
int mKeyboardfocus;
int mMinimized;
int mMousefocus;
}windowku[TOTAL_WINDOWS];
int event_window(SDL_Event *e, info_window *twindow){
if( e->window.windowID == twindow->idwindow ){
switch( e->window.event ){
//windowterlihat
case SDL_WINDOWEVENT_SHOWN:
twindow->tutup=salah;
break;
//Window menghilang
case SDL_WINDOWEVENT_HIDDEN:
twindow->tutup=benar;
break;
//Get new dimensions and repaint
case SDL_WINDOWEVENT_SIZE_CHANGED:
twindow->lebar = e->window.data1;
twindow->tinggi = e->window.data2;
SDL_RenderPresent( twindow->mrenderer );
break;
case SDL_WINDOWEVENT_EXPOSED:
SDL_RenderPresent( twindow->mrenderer );
break;
//Mouse enter
case SDL_WINDOWEVENT_ENTER:
twindow->
mMousefocus=benar;
break;
//Mouse exit
case SDL_WINDOWEVENT_LEAVE:
twindow->
mMousefocus=salah;
break;
//Keyboard focus gained
case SDL_WINDOWEVENT_FOCUS_GAINED:
twindow->
mKeyboardfocus=benar;
break;
//Keyboard focus lost
case SDL_WINDOWEVENT_FOCUS_LOST:
twindow->
mKeyboardfocus=salah;
break;
//Window minimized
case SDL_WINDOWEVENT_MINIMIZED:
twindow->
mMinimized=benar;
break;
//Window maxized
case SDL_WINDOWEVENT_MAXIMIZED:
twindow->
mMinimized=salah;
break;
//Window restored
case SDL_WINDOWEVENT_RESTORED:
twindow->mMinimized=salah;
break;
case SDL_WINDOWEVENT_CLOSE:
SDL_HideWindow( twindow->mwindow);
break;
}
}
return 0;
}
int buat_window(const char *nama, info_window *twindow){
twindow->mwindow=SDL_CreateWindow(nama, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if( twindow->mwindow == NULL ){
printf( "Error : %s", SDL_GetError() );
return 0;
}else{
twindow->mrenderer = SDL_CreateRenderer(twindow->mwindow, -1, SDL_RENDERER_ACCELERATED);
if(twindow->mrenderer!=NULL){
SDL_SetRenderDrawColor(twindow->mrenderer, 0xFF, 0xFF, 0xFF, 0xFF);
twindow->idwindow=SDL_GetWindowID(twindow->mwindow);
twindow->tutup=salah;
}else{
SDL_DestroyWindow( twindow->mwindow );
twindow->tutup=benar;
twindow->mwindow=NULL;
return 0;
}
}
return 1;
}
int main(int argc, char* args[]){
SDL_Event evt;
int hasil;
if( SDL_Init( SDL_INIT_VIDEO ) < 0){
printf( "Error: %s\n", SDL_GetError() );
}else{
for(int i=0;i<TOTAL_WINDOWS;i++){
hasil+=buat_window("SDL_test", &windowku[i]);
}
if(hasil>=TOTAL_WINDOWS){
int berhenti=salah;
while(berhenti==salah){
while(SDL_PollEvent(&evt)){
switch(evt.type){
case SDL_WINDOWEVENT :
for( int i = 0; i < TOTAL_WINDOWS; i++ ){
event_window(&evt, &windowku[i]);
}
break;
case SDL_KEYDOWN:
switch(evt.key.keysym.sym){
case SDLK_1:
SDL_ShowWindow(windowku[0].mwindow);
SDL_RaiseWindow(windowku[0].mwindow);
break;
case SDLK_2:
SDL_ShowWindow(windowku[1].mwindow);
SDL_RaiseWindow(windowku[1].mwindow);
break;
case SDLK_3:
SDL_ShowWindow(windowku[2].mwindow);
SDL_RaiseWindow(windowku[2].mwindow);
break;
}
}
}
for(int i=0;i<TOTAL_WINDOWS;i++){
SDL_RenderClear(windowku[i].mrenderer);
SDL_RenderPresent(windowku[i].mrenderer);
}
int semua_tutup=benar;
for(int i=0;i<TOTAL_WINDOWS;i++){
if(windowku[i].tutup==salah){
semua_tutup=salah;
break;
}
}
if(semua_tutup==benar)berhenti=benar;
}
}
}
for(int i=0;i<3;i++)SDL_DestroyWindow( windowku[i].mwindow );
SDL_Quit();
return 0;
}