📄 win_cfg.c
字号:
/* Digger Remastered
Copyright (c) Andrew Jenner 1998-2004 */
#include "def.h"
#include "win_dig.h"
#include "win_cfg.h"
#include "win_snd.h"
#include "win_vid.h"
#include "resource.h"
#include "hardware.h"
#include <windowsx.h>
#include <commctrl.h>
#include "sprite.h" //for now
/**********************************************************************/
/* some external variables that are read/changed on the config screen */
/**********************************************************************/
extern bool soundflag,musicflag;
extern Uint5 ftime;
extern Uint4 size;
/**********************************************************************/
/* g_hWndConfigWindow handle of the main configuration window */
/* |__ g_hWndTabControl handle of the tab control */
/* |___ g_hDlg handle of the currently displayed page */
/**********************************************************************/
HWND g_hWndConfigWindow=NULL;
HWND g_hWndTabControl=NULL;
HWND g_hDlg=NULL;
RECT rcClientRect;
RECT tempRect;
#define WM_FILL_TREEVIEW WM_USER+1
struct KEY_NAME_STRUCT
{
char *key_name;
int key_code;
};
char UNKNOWN_KEY_NAME[]="(unknown key)";
struct KEY_NAME_STRUCT key_list[]={
"NumPad 0",VK_NUMPAD0,
"NumPad 1",VK_NUMPAD1,
"NumPad 2",VK_NUMPAD2,
"NumPad 3",VK_NUMPAD3,
"NumPad 4",VK_NUMPAD4,
"NumPad 5",VK_NUMPAD5,
"NumPad 6",VK_NUMPAD6,
"NumPad 7",VK_NUMPAD7,
"NumPad 8",VK_NUMPAD8,
"NumPad 9",VK_NUMPAD9,
"NumPad *",VK_MULTIPLY,
"NumPad /",VK_DIVIDE,
"NumPad +",VK_ADD,
"NumPad -",VK_SUBTRACT,
"NumPad .",VK_DECIMAL,
"F1" ,VK_F1,
"F2" ,VK_F2,
"F3" ,VK_F3,
"F4" ,VK_F4,
"F5" ,VK_F5,
"F6" ,VK_F6,
"F7" ,VK_F7,
"F8" ,VK_F8,
"F9" ,VK_F9,
"F10" ,VK_F10,
"F11" ,VK_F11,
"F12" ,VK_F12,
"F13" ,VK_F13,
"F14" ,VK_F14,
"F15" ,VK_F15,
"F16" ,VK_F16,
"F17" ,VK_F17,
"F18" ,VK_F18,
"F19" ,VK_F19,
"F20" ,VK_F20,
"F21" ,VK_F21,
"F22" ,VK_F22,
"F23" ,VK_F23,
"F24" ,VK_F24,
"ArrowLeft" ,VK_LEFT,
"ArrowRight",VK_RIGHT,
"ArrowUp" ,VK_UP,
"ArrowDown" ,VK_DOWN,
"A" ,'A',
"B" ,'B',
"C" ,'C',
"D" ,'D',
"E" ,'E',
"F" ,'F',
"G" ,'G',
"H" ,'H',
"I" ,'I',
"J" ,'J',
"K" ,'K',
"L" ,'L',
"M" ,'M',
"N" ,'N',
"O" ,'O',
"P" ,'P',
"Q" ,'Q',
"R" ,'R',
"S" ,'S',
"T" ,'T',
"U" ,'U',
"V" ,'V',
"W" ,'W',
"X" ,'X',
"Y" ,'Y',
"Z" ,'Z',
"Tab" ,VK_TAB,
"Backspace" ,VK_BACK,
"Enter" ,VK_RETURN,
"CapsLock" ,VK_CAPITAL,
"NumLock" ,VK_NUMLOCK,
"ScrollLock",VK_SCROLL,
"Shift" ,VK_SHIFT,
"Control" ,VK_CONTROL,
"Pause" ,VK_PAUSE,
"Space" ,VK_SPACE,
"Escape" ,VK_ESCAPE,
"1" ,'1',
"2" ,'2',
"3" ,'3',
"4" ,'4',
"5" ,'5',
"6" ,'6',
"7" ,'7',
"8" ,'8',
"9" ,'9',
"Clear" ,VK_CLEAR,
"`" ,0x00C0
};
struct KEY_MAPPINGS_STRUCT
{
int key_code;
struct KEY_MAPPING_STRUCT* next;
};
// 18=save DRF, 19=toggle # players
struct KEY_MAPPINGS_STRUCT* key_mappings[19]={NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,
NULL};
#define SIZEOF_KEY_MAPPINGS_LIST (sizeof(key_mappings)/sizeof(key_mappings[0]))
int cur_key_map_idx=0;
struct CFG_AUDIO_SETTINGS_STRUCT
{
bool disabled;
enum CFG_AUDIO_SETTING_OUTPUT_DEVICE_ENUM output_device;
LONG volume;
bool play_sounds;
bool play_music;
Uint4 buffer_size;
DWORD freq;
};
struct CFG_VIDEO_SETTINGS_STRUCT
{
bool use_directdraw;
bool hardware_video_mode; /* video mode to use for the video adapter */
bool graphics_mode; /* which set of sprites, etc. to use: cga, vga, etc. */
bool use_async_updates; /* FALSE = like original game with flashing sprites */
int preferred_video_mode_index;
};
struct CFG_GAME_SETTINGS_STRUCT
{
Uint5 speed;
};
struct CFG_SETTINGS_STRUCT
{
struct CFG_AUDIO_SETTINGS_STRUCT audio;
struct CFG_VIDEO_SETTINGS_STRUCT video;
struct CFG_GAME_SETTINGS_STRUCT game;
} cfg;
extern void (*gpal)(Sint4 pal);
LRESULT CALLBACK ConfigWndProc (HWND hWndConfigWindow, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ConfigTabDlgWndProc (HWND hWndPage, UINT message, WPARAM wParam, LPARAM lParam);
void init_video_config_page(HWND hWndTabControl);
void init_audio_config_page(HWND hWndTabControl);
void init_input_config_page(HWND hWndTabControl);
void hide_video_config_page(HWND hWndTabControl);
void hide_audio_config_page(HWND hWndTabControl);
void hide_input_config_page(hWndConfigWindow);
void apply_new_cfg_settings();
void retrieve_current_cfg_settings();
char* get_key_name(int code);
BOOL is_key_bound(int key_code, int function);
void load_mapped_key_list(HWND control);
void clear_mapped_keys(int idx);
void store_mapped_keys();
/***********************************/
/* function definitions */
/***********************************/
bool create_config_window()
{
WNDCLASS wndClass;
int width;
int height;
retrieve_current_cfg_settings();
suspend_game=TRUE;
pause_windows_sound_playback();
if (!g_bWindowed)
{
attach_clipper();
IDirectDrawSurface_SetPalette(g_pDDSPrimary, NULL);
}
SetMenu(hWnd, GetMenu(hWnd));
show_mouse_cursor();
width = 400;
height = 300;
rcClientRect.left = 0;
rcClientRect.top = 0;
rcClientRect.right = rcClientRect.left + width;
rcClientRect.bottom = rcClientRect.top + height;
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = ConfigWndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = g_hInstance;
wndClass.hIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_ICON1));
wndClass.hCursor = LoadCursor ((HINSTANCE) NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "DiggerInputConfig";
RegisterClass(&wndClass);
cur_dialog_box=g_hWndConfigWindow = CreateWindowEx(
WS_EX_WINDOWEDGE,
"DiggerInputConfig",
"Controls",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER,
(GetSystemMetrics(SM_CXFULLSCREEN) - width) / 2,
(GetSystemMetrics(SM_CYFULLSCREEN) - height) / 2,
width,
height,
(HWND) hWnd,
(HMENU) NULL,
(HINSTANCE) g_hInstance,
(void FAR*) NULL );
ShowWindow(g_hWndConfigWindow, SW_SHOW);
UpdateWindow(g_hWndConfigWindow);
EnableWindow(hWnd,FALSE);
return TRUE;
}
LRESULT CALLBACK bind_key_from_list_dialog_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL success;
UINT rval;
TV_ITEM tree_item;
TV_INSERTSTRUCT tree_item_struct;
char strbuf[80];
HWND control;
HTREEITEM root_item;
HTREEITEM new_item;
int i;
int state;
static bool list_drawn=FALSE;
struct KEY_MAPPINGS_STRUCT *next;
switch (uMsg)
{
case WM_INITDIALOG:
list_drawn=FALSE;
/* Setting the 'checked' state of an item in TreeView does
not seem to work within WM_INITDIALOG for some reason,
so set a flag indicating that TreeView needs to be filled later.
The list is actually filled after the dialog box is drawn
on the screen for the first time.
*/
return TRUE;
case WM_PAINT:
if (!list_drawn)
{
list_drawn=TRUE;
PostMessage(hDlg,WM_FILL_TREEVIEW,0,0);
}
break;
case WM_FILL_TREEVIEW:
control = GetDlgItem(hDlg,IDC_TREE_AVAILABLE_CONTROLS);
// put "Keyboard" heading in root of tree
tree_item_struct.hParent=NULL;
tree_item_struct.hInsertAfter=TVI_LAST;
tree_item_struct.item.mask=TVIF_TEXT | TVIF_PARAM | TVIF_STATE;
tree_item_struct.item.pszText="Keyboard";
tree_item_struct.item.lParam=0;
tree_item_struct.item.state=INDEXTOSTATEIMAGEMASK(1);
tree_item_struct.item.stateMask=TVIS_STATEIMAGEMASK;
root_item=TreeView_InsertItem(control, &tree_item_struct);
// add key names from key_list
tree_item_struct.hParent = root_item;
for (i=0;i<(sizeof(key_list)/sizeof(key_list[0]));i++)
{
tree_item_struct.item.mask=TVIF_TEXT | TVIF_PARAM | TVIF_STATE;
if (is_key_bound(key_list[i].key_code, cur_key_map_idx))
tree_item_struct.item.state=INDEXTOSTATEIMAGEMASK(2);
else
tree_item_struct.item.state=INDEXTOSTATEIMAGEMASK(1);
tree_item_struct.item.stateMask=TVIS_STATEIMAGEMASK;
tree_item_struct.item.pszText=key_list[i].key_name;
tree_item_struct.item.lParam=key_list[i].key_code;
new_item=TreeView_InsertItem(control, &tree_item_struct);
}
break;
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_CLOSE:
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hDlg, FALSE);
return TRUE;
case IDOK:
clear_mapped_keys(cur_key_map_idx);
/* map selected keys to this function */
control = GetDlgItem(hDlg,IDC_TREE_AVAILABLE_CONTROLS);
root_item=TreeView_GetRoot(control);
new_item=TreeView_GetNextItem(control,root_item,TVGN_CHILD);
while (new_item)
{
tree_item.hItem=new_item;
tree_item.mask=TVIF_PARAM | TVIF_TEXT | TVIF_STATE;
tree_item.stateMask=TVIS_STATEIMAGEMASK;
tree_item.pszText=strbuf;
TreeView_GetItem(control,&tree_item);
state=tree_item.state >>12;
if (state==2)
{
add_mapped_key(cur_key_map_idx, tree_item.lParam);
}
new_item=TreeView_GetNextItem(control,new_item,TVGN_NEXT);
};
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
return FALSE;
}
LRESULT CALLBACK ConfigWndProc (HWND hWndConfigWindow, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND control;
int iPage; /* currently displayed page/tab */
TC_ITEM tc_item;
memset(&tc_item,0, sizeof(TC_ITEM));
tc_item.mask = TCIF_TEXT;
switch(message)
{
case WM_KEYDOWN:
return DefWindowProc(hWndConfigWindow, message, wParam, lParam);
case WM_CREATE:
GetClientRect(hWndConfigWindow, &rcClientRect);
g_hWndTabControl = CreateWindow(
WC_TABCONTROL, "",
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | WS_TABSTOP | WS_GROUP,
rcClientRect.left, rcClientRect.top, rcClientRect.right - rcClientRect.left, rcClientRect.bottom - rcClientRect.top - 34,
hWndConfigWindow, NULL, g_hInstance, NULL
);
control=CreateWindow("BUTTON","OK",BS_DEFPUSHBUTTON | WS_CHILD, rcClientRect.right - 60, rcClientRect.bottom - 32, 60,30,hWndConfigWindow, (HMENU) IDC_BUTTON_OK, g_hInstance, NULL );
ShowWindow(control,SW_SHOW);
tc_item.pszText = "Video";
TabCtrl_InsertItem(g_hWndTabControl,0,&tc_item);
tc_item.pszText = "Audio";
TabCtrl_InsertItem(g_hWndTabControl,1,&tc_item);
tc_item.pszText = "Controls";
TabCtrl_InsertItem(g_hWndTabControl,2,&tc_item);
tc_item.pszText = "System";
TabCtrl_InsertItem(g_hWndTabControl,3,&tc_item);
TabCtrl_SetCurSel(g_hWndTabControl,0);
GetClientRect(g_hWndTabControl,&tempRect);
TabCtrl_AdjustRect(g_hWndTabControl,FALSE, &tempRect);
init_video_config_page(hWndConfigWindow);
return 0;
case WM_NOTIFY:
switch (((NMHDR FAR *)lParam)->code)
{
case TCN_SELCHANGING: /* current page is about of be removed */
if (g_hDlg!=NULL)
{
iPage = TabCtrl_GetCurSel(g_hWndTabControl);
switch (iPage)
{
case 0:
hide_video_config_page(hWndConfigWindow);
break;
case 1:
hide_audio_config_page(hWndConfigWindow);
break;
case 2:
hide_input_config_page(hWndConfigWindow);
break;
}
if (DestroyWindow(g_hDlg))
g_hDlg=0;
}
return FALSE;
case TCN_SELCHANGE: /* new page is about to be display */
iPage = TabCtrl_GetCurSel(g_hWndTabControl);
switch (iPage)
{
case 0:
init_video_config_page(hWndConfigWindow);
break;
case 1:
init_audio_config_page(hWndConfigWindow);
break;
case 2:
init_input_config_page(hWndConfigWindow);
break;
}
return FALSE;
case NM_SETFOCUS:
if ((int) wParam == IDC_INVISIBLE_TABSTOP)
{
return FALSE;
}
break;
default:
return FALSE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BUTTON_CANCEL:
EndDialog(hWndConfigWindow, FALSE);
return TRUE;
case IDC_BUTTON_OK:
PostMessage(hWndConfigWindow,WM_CLOSE,(WPARAM) 0, (LPARAM) 0);
return TRUE;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -