WindowModeSelecter.zip/WindowModeSelecter.c
#include <windows.h>
#pragma comment (lib,"gdi32.lib")
#pragma comment (lib,"winmm.lib")
//グローバル変数ここから
int __dialog_ret = -2;
FARPROC __button_proc;
HWND *__radio=NULL;
HWND __button;
//グローバル変数ここまで
//ボタンプロシージャー割り込み用
LRESULT CALLBACK __SubWndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
switch(msg){
case WM_KEYUP:
switch(wp){
case VK_RETURN:
//無理やりクリックされた時と同じ挙動を起こす
CallWindowProc((WNDPROC)__button_proc, hwnd, WM_LBUTTONDOWN, 0, 0);
return (CallWindowProc((WNDPROC)__button_proc, hwnd, WM_LBUTTONUP, 0, 0));
}
break;
}
//本来のプロシージャーを実行する
return (CallWindowProc((WNDPROC)__button_proc, hwnd, msg, wp, lp));
}
//テキストウィンドウのプロシージャー
LRESULT CALLBACK __TextWndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
HDC hdc;
PAINTSTRUCT paint;
HGDIOBJ temp;
char str[1024];
char *s;
int i;
switch (msg) {
case WM_CREATE:
break;
case WM_PAINT:
hdc = BeginPaint(hwnd,&paint);
SetTextColor(hdc,COLOR_MENUTEXT);
SetBkColor(hdc,GetSysColor(COLOR_BTNFACE));
temp = SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
GetWindowText(hwnd,str,1024);
s = strtok(str,"\n");
i = 0;
while(s!=NULL){
TextOut(hdc,0,i*15,s,strlen(s));
s = strtok(NULL,"\n");
i++;
}
SelectObject(hdc,temp);//変更前のフォントに戻す
EndPaint(hwnd,&paint);
break;
}
return DefWindowProc(hwnd , msg , wp , lp);
}
//ウィンドウプロシージャー
LRESULT CALLBACK __WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
int i;
switch (msg) {
case WM_CLOSE://×ボタンを押された場合は終了する
__dialog_ret = -1;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
if(wp==SIZE_MAXIMIZED){
ShowWindow(hwnd,SW_SHOWNORMAL);
return 0;
}
break;
case WM_COMMAND:
if((HWND)lp==__button){//ボタンが押された場合、ダイアログを閉じる
return DefWindowProc(hwnd , WM_CLOSE , 0 , 0);
}
if(__radio!=NULL){
i = 0;
while(__radio[i]!=NULL){
if((HWND)lp==__radio[i]){
__dialog_ret = i;
break;
}
i++;
}
}
break;
default:
break;
}
return DefWindowProc(hwnd , msg , wp , lp);
}
void __JoyLoop(void){
JOYINFOEX JoyInfoEx;
static int flag = 0;
JoyInfoEx.dwSize = sizeof(JOYINFOEX);
JoyInfoEx.dwFlags = JOY_RETURNALL;
if(joyGetPosEx(0, &JoyInfoEx) == JOYERR_NOERROR){
if(JoyInfoEx.dwButtons & JOY_BUTTON1){
SendMessage(__button,WM_KEYUP,(WPARAM)VK_RETURN,(LPARAM)0);
}
if(flag !=1 && JoyInfoEx.dwYpos < 0x7FFF - 0x4000){
SendMessage(__radio[__dialog_ret] , BM_SETCHECK ,FALSE, 0);
__dialog_ret-=1;
if(__dialog_ret==-1){
while(__radio[__dialog_ret+1]!=0)__dialog_ret++;
}
SendMessage(__radio[__dialog_ret] , BM_SETCHECK ,TRUE, 0);
flag = 1;
} else if(flag != -1 && JoyInfoEx.dwYpos > 0x7FFF + 0x4000){
SendMessage(__radio[__dialog_ret] , BM_SETCHECK ,FALSE, 0);
__dialog_ret+=1;
if(__radio[__dialog_ret]==0){
__dialog_ret = 0;
}
SendMessage(__radio[__dialog_ret] , BM_SETCHECK ,TRUE, 0);
flag = -1;
} else {
flag = 0;
}
}
}
/*
・ラジオボタンによる選択ダイアログ生成汎用関数
str:選択肢及びタイトルとボタンの名称
str[0]:タイトル
str[1]:決定ボタンの名称
str[2]:表示する説明文(1行)
str[3〜num+2]:選択肢の名称
num:選択肢の個数
def:デフォルトで選択しておく選択肢
返り値:選択された選択肢の番号
ダイアログが閉じられたもしくは何らかの理由で処理失敗した場合は-1
*/
int CreateSelectWindow(char **str,int num,int def){
HWND hwnd;
MSG msg;
WNDCLASS winc;
HINSTANCE hInst = GetModuleHandle(NULL);
int i,ret,w,h,count;
while(__dialog_ret!=-2)Sleep(100);
if(def>=num || def<0 || num<1 || str==NULL){//引数がおかしい時例外を起こす
RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED,0,0,NULL);
num = 0;
}
__dialog_ret = def;
memset(&winc,0,sizeof(WNDCLASS));
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = __TextWndProc;
winc.hInstance = hInst;
winc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
winc.lpszClassName = TEXT("TEXT");
if (!RegisterClass(&winc)){
ret = -1;
goto END4;
}
memset(&winc,0,sizeof(WNDCLASS));
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = __WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInst;
winc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
winc.lpszClassName = TEXT("RadioButtonSelecter");
if (!RegisterClass(&winc)){
ret = -1;
goto END3;
}
count = 1;
i = 0;
while(str[2][i] != '\0'){
if(str[2][i]=='\n')count++;
i++;
}
w = 180;
h = 65+(num+count)*15;
hwnd = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_DLGMODALFRAME, TEXT("RadioButtonSelecter") , str[0] ,
WS_POPUP | WS_CAPTION | WS_SYSMENU,
(GetSystemMetrics(SM_CXSCREEN)-w)/2 , (GetSystemMetrics(SM_CYSCREEN)-h)/2 ,
w , h , NULL , NULL , hInst , NULL
);
if (hwnd == NULL){
ret = -1;
goto END2;
}
if(CreateWindow(
TEXT("TEXT") , str[2] ,
WS_CHILD | WS_VISIBLE ,
9 , 5 , 156 , 15*count ,
hwnd , NULL , hInst , NULL
) == NULL){
ret = -1;
goto END2;
}
__radio = (HWND*)malloc((1+num)*sizeof(HWND));
if(__radio == NULL){
ret = -1;
goto END2;
}
memset(__radio,0,(1+num)*sizeof(HWND));
i = 0;
while(i < num){
if((__radio[i] = CreateWindow(
TEXT("BUTTON") , str[i+3] ,
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON ,
11 , 8+(i+count)*15 , 152 , 15 ,
hwnd , NULL , hInst , NULL
)) == NULL){
ret = -1;
goto END;
}
SendMessage(__radio[i],WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),(LPARAM)TRUE);
i++;
}
if((__button = CreateWindow(
TEXT("BUTTON") , str[1] ,
WS_CHILD | WS_VISIBLE ,
49 , 13+(i+count)*15 , 76 , 24 ,
hwnd , NULL , hInst , NULL
)) == NULL){
ret = -1;
goto END;
}
SendMessage(__button,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),(LPARAM)TRUE);
SendMessage(__radio[__dialog_ret] , BM_SETCHECK ,TRUE, 0);
SetFocus(__button);
__button_proc = (FARPROC)GetWindowLong(__button, GWL_WNDPROC);
SetWindowLong(__button, GWL_WNDPROC, (LONG)__SubWndProc);
ShowWindow(hwnd,SW_SHOWNORMAL);
do{
__JoyLoop();
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(60);
}while(msg.message!=WM_QUIT);
ret = __dialog_ret;
__dialog_ret = -2;
END:
free(__radio);
END2:
UnregisterClass(TEXT("RadioButtonSelecter"),hInst);
END3:
UnregisterClass(TEXT("TEXT"),hInst);
END4:
return ret;
}
/*
・ラジオボタンによる選択ダイアログ生成汎用関数その2
title:タイトルの名称
button:ボタンの名称
caption:表示する説明文(1行)
item:選択肢の名称
num:選択肢の個数
def:デフォルトで選択しておく選択肢
返り値:選択された選択肢の番号
ダイアログが閉じられたもしくは何らかの理由で処理失敗した場合は-1
備考:
CreateSelectWindowのラッパー関数
単純にtitleとbuttonとcaptionを分けてわかりやすくしただけ。
*/
int CreateSelectWindow2(char *title,char *button,char *caption,char **item,int num,int def){
char **str;
int ret;
str = (char**)malloc(sizeof(char**)*(3+num));
if(str==NULL)return -1;
str[0] = title;
str[1] = button;
str[2] = caption;
memcpy(&str[3],item,sizeof(char**)*num);
ret = CreateSelectWindow(str,num,def);
free(str);
return ret;
}
/*
・ウィンドウモード選択用ダイアログ生成関数
title:ダイアログ上に表示するタイトル
def:デフォルトの起動モード(1でウィンドウ、0でフルスクリーン)
返り値:ウィンドウモード=1、フルスクリーン=0
ダイアログが閉じられたもしくは何らかの理由で処理失敗した場合は-1
備考:×ボタンが押されても終了せず処理続行したい場合に使用します。
*/
int CheckWindowMode2(char *title,int def){
static char item[][256] = {"フルスクリーン","ウィンドウモード"};
static char *str[] = {item[0],item[1]};
return CreateSelectWindow2(title,"ゲーム起動","ウィンドウモードを選択してください",str,2,def);
}
/*
・ウィンドウモード選択用ダイアログ生成関数
title:ダイアログ上に表示するタイトル
def:デフォルトの起動モード(1でウィンドウ、0でフルスクリーン)
返り値:ウィンドウモード=1、フルスクリーン=0
*/
int CheckWindowMode(char *title,int def){
int ret;
ret = CheckWindowMode2(title,def);
if(ret == -1)exit(0);
return ret;
}
/*
備考:
title,button,item,captionのうちcaptionのみ改行が可能です。
他の項目は改行できません。
本コード上ではグローバル変数で以下の四つの名前を使用しています。
__dialog_ret
__button_proc
__radio
__button
関数名では以下の七つの名前を使用しています。
__WndProc
__SubWndProc
__TextWndProc
CreateSelectWindow
CreateSelectWindow2
CheckWindowMode
CheckWindowMode2
*/