📄 combobox.c
字号:
/*
** $Id: combobox.c,v 1.54 2004/04/13 11:57:27 snig Exp $
**
** cobmobox.c: the cobmobox control.
**
** Copyright (C) 2003 Feynman Software
** Copyright (C) 2001 ~ 2002 Wei Yongming
**
** NOTE: Originally by Wang Jian
**
** Create date: 2001/08/06
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
** TODO:
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "window.h"
#include "control.h"
#include "cliprect.h"
#include "internals.h"
#include "ctrlclass.h"
#ifdef _CTRL_COMBOBOX
#include "combobox.h"
#include "ctrlmisc.h"
#define LEN_SPINVALUE 50
#define IDC_CEDIT 100
#define IDC_CLISTBOX 101
#define INTER_EDIT_BUTTON 2
#define INTER_EDIT_LISTBOX 4
#define DEF_LISTHEIGHT 60
static const BITMAP* bmp_downarrow;
static const BITMAP* bmp_updownarrow;
static const BITMAP* bmp_leftrightarrow;
#define ARROWBMP_DOWN bmp_downarrow
#define ARROWBMP_UPDOWN bmp_updownarrow
#define ARROWBMP_LEFTRIGHT bmp_leftrightarrow
static int ComboBoxCtrlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
BOOL RegisterComboBoxControl (void)
{
WNDCLASS WndClass;
#ifdef _PHONE_WINDOW_STYLE
if ((bmp_downarrow = GetStockBitmap (STOCKBMP_DOWNARROW, 0, 0)) == NULL)
return FALSE;
if ((bmp_updownarrow = GetStockBitmap (STOCKBMP_UPDOWNARROW, 0, 0)) == NULL)
return FALSE;
if ((bmp_leftrightarrow = GetStockBitmap (STOCKBMP_LEFTRIGHTARROW, 0, 0)) == NULL)
return FALSE;
#else
if ((bmp_downarrow = GetStockBitmap (STOCKBMP_DOWNARROW, -1, -1)) == NULL)
return FALSE;
if ((bmp_updownarrow = GetStockBitmap (STOCKBMP_UPDOWNARROW, -1, -1)) == NULL)
return FALSE;
if ((bmp_leftrightarrow = GetStockBitmap (STOCKBMP_LEFTRIGHTARROW, -1, -1)) == NULL)
return FALSE;
#endif
WndClass.spClassName = CTRL_COMBOBOX;
WndClass.dwStyle = WS_NONE;
WndClass.dwExStyle = WS_EX_NONE;
WndClass.hCursor = GetSystemCursor (0);
WndClass.iBkColor = GetWindowElementColor (BKC_CONTROL_DEF);
WndClass.WinProc = ComboBoxCtrlProc;
return AddNewControlClass (&WndClass) == ERR_OK;
}
static int AutoSpinEditBoxProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam )
{
WNDPROC old_edit_proc;
if (message == MSG_CHAR) {
if (wParam < '0' || wParam > '9')
return 0;
}
old_edit_proc = (WNDPROC) GetWindowAdditionalData (hWnd);
return (*old_edit_proc) (hWnd, message, wParam, lParam);
}
static int DefCBProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
static void ComboBoxDrawSpinButton (HWND hwnd, HDC hdc)
{
PCOMBOBOXDATA pData;
PCONTROL pCtrl;
pCtrl = Control (hwnd);
pData = (PCOMBOBOXDATA)pCtrl->dwAddData2;
switch (pCtrl->dwStyle & CBS_TYPEMASK) {
case CBS_SPINLIST:
case CBS_AUTOSPIN:
if (pCtrl->dwStyle & CBS_SPINARROW_LEFTRIGHT) {
FillBoxWithBitmapPart (hdc, pData->IncSpinBox.left, pData->IncSpinBox.top,
pData->SpinBmp->bmWidth/2, pData->SpinBmp->bmHeight,
0, 0, pData->SpinBmp, pData->SpinBmp->bmWidth/2, 0);
FillBoxWithBitmapPart (hdc, pData->DecSpinBox.left, pData->DecSpinBox.top,
pData->SpinBmp->bmWidth/2, pData->SpinBmp->bmHeight,
0, 0, pData->SpinBmp, 0, 0);
}
else {
FillBoxWithBitmapPart (hdc, pData->IncSpinBox.left, pData->IncSpinBox.top,
pData->SpinBmp->bmWidth, pData->SpinBmp->bmHeight/2,
0, 0, pData->SpinBmp, 0, 0);
FillBoxWithBitmapPart (hdc, pData->DecSpinBox.left, pData->DecSpinBox.top,
pData->SpinBmp->bmWidth, pData->SpinBmp->bmHeight/2,
0, 0, pData->SpinBmp, 0, pData->SpinBmp->bmHeight/2);
}
break;
default:
if (pData->SpinBmp)
FillBoxWithBitmap (hdc,
pData->IncSpinBox.left, pData->IncSpinBox.top, 0, 0,
pData->SpinBmp);
break;
}
}
static void GetSpinBox (PCOMBOBOXDATA pData, DWORD dwStyle, const RECT* rect, RECT* edit_box)
{
if (dwStyle & CBS_SPINARROW_TOPBOTTOM) {
pData->SpinBmp = ARROWBMP_UPDOWN;
edit_box->left = rect->left;
edit_box->top = rect->top + bmp_updownarrow->bmHeight/2 + INTER_EDIT_BUTTON;
edit_box->right = rect->right;
edit_box->bottom = rect->bottom - bmp_updownarrow->bmHeight/2 - INTER_EDIT_BUTTON;
pData->IncSpinBox.left = (rect->right - bmp_updownarrow->bmWidth)/2;
pData->IncSpinBox.right = pData->IncSpinBox.left + bmp_updownarrow->bmWidth;
pData->IncSpinBox.top = rect->top;
pData->IncSpinBox.bottom = rect->top + bmp_updownarrow->bmHeight/2;
pData->DecSpinBox.left = pData->IncSpinBox.left;
pData->DecSpinBox.right = pData->IncSpinBox.right;
pData->DecSpinBox.top = rect->bottom - bmp_updownarrow->bmHeight/2;
pData->DecSpinBox.bottom = rect->bottom;
}
else if (dwStyle & CBS_SPINARROW_LEFTRIGHT) {
pData->SpinBmp = ARROWBMP_LEFTRIGHT;
edit_box->left = rect->left + bmp_updownarrow->bmWidth/2 + INTER_EDIT_BUTTON*2;
edit_box->top = rect->top;
edit_box->bottom = rect->bottom;
edit_box->right = rect->right - bmp_updownarrow->bmWidth/2 - INTER_EDIT_BUTTON*2;
pData->DecSpinBox.left = rect->left;
pData->DecSpinBox.top = (rect->bottom - bmp_leftrightarrow->bmHeight)/2;
pData->DecSpinBox.right = rect->left + bmp_leftrightarrow->bmWidth/2;
pData->DecSpinBox.bottom = pData->DecSpinBox.top + bmp_updownarrow->bmHeight;
pData->IncSpinBox.left = rect->right - bmp_updownarrow->bmWidth/2 - INTER_EDIT_BUTTON;
pData->IncSpinBox.top = pData->DecSpinBox.top;
pData->IncSpinBox.right = rect->right - INTER_EDIT_BUTTON;
pData->IncSpinBox.bottom = pData->DecSpinBox.bottom;
}
else {
int vcenter = (rect->bottom - rect->top)/2;
pData->SpinBmp = ARROWBMP_UPDOWN;
edit_box->left = rect->left;
edit_box->top = rect->top;
edit_box->bottom = rect->bottom;
edit_box->right = rect->right - bmp_updownarrow->bmWidth - INTER_EDIT_BUTTON;
pData->IncSpinBox.left = rect->right - bmp_updownarrow->bmWidth;
pData->IncSpinBox.top = vcenter - bmp_updownarrow->bmHeight/2 - 1;
pData->IncSpinBox.right = rect->right;
pData->IncSpinBox.bottom = pData->IncSpinBox.top + bmp_updownarrow->bmHeight/2;
pData->DecSpinBox.left = pData->IncSpinBox.left;
pData->DecSpinBox.top = vcenter + 1;
pData->DecSpinBox.right = pData->IncSpinBox.right;
pData->DecSpinBox.bottom = pData->DecSpinBox.top + bmp_updownarrow->bmHeight/2;
}
}
static int ComboBoxCtrlProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam)
{
PCONTROL pCtrl = Control (hwnd);
PCOMBOBOXDATA pData = (PCOMBOBOXDATA)pCtrl->dwAddData2;
DWORD dwStyle = pCtrl->dwStyle;
switch (message) {
case MSG_CREATE:
{
RECT rect, edit_box;
int height, width, list_height;
int tmpx, tmpy;
const char* edit_text = GetWindowCaption (hwnd);
DWORD list_style, edit_style;
if (!(pData = calloc (1, sizeof (COMBOBOXDATA)))) {
fprintf (stderr, "Create ComboBox control failure!\n");
return -1;
}
pData->wStateFlags = 0;
pData->nListItems = 0;
pCtrl->dwAddData2 = (DWORD)pData;
GetClientRect (hwnd, &rect);
width = rect.right - rect.left;
list_style = WS_VSCROLL | LBS_NOTIFY | WS_THINFRAME;
if (dwStyle & CBS_SORT) list_style |= LBS_SORT;
edit_style = WS_CHILD | WS_VISIBLE;
if (!(dwStyle & CBS_EDITNOBORDER)) edit_style |= WS_BORDER;
if (dwStyle & CBS_EDITBASELINE) edit_style |= ES_BASELINE;
if (dwStyle & CBS_UPPERCASE) edit_style |= ES_UPPERCASE;
if (dwStyle & CBS_LOWERCASE) edit_style |= ES_LOWERCASE;
if (dwStyle & CBS_READONLY) edit_style |= ES_READONLY;
switch (dwStyle & CBS_TYPEMASK) {
case CBS_SIMPLE:
height = GetSysFontHeight (SYSLOGFONT_CONTROL)
+ MARGIN_EDIT_TOP + MARGIN_EDIT_BOTTOM + (WIDTH_EDIT_BORDER<<1);
edit_box.left = rect.left;
edit_box.top = rect.top;
edit_box.right = rect.left + width;
edit_box.bottom = rect.top + height;
list_height = (pCtrl->dwAddData > 0) ? pCtrl->dwAddData : DEF_LISTHEIGHT;
list_style |= WS_VISIBLE | WS_BORDER;
width -= GetMainWinMetrics (MWM_ICONX);
pData->SpinBmp = 0;
pData->ListBoxRect.left = rect.left + GetMainWinMetrics (MWM_ICONX);
pData->ListBoxRect.right = rect.right - MARGIN_EDIT_RIGHT;
pData->ListBoxRect.top = rect.top + height + INTER_EDIT_LISTBOX;
pData->ListBoxRect.bottom = pData->ListBoxRect.top + list_height;
break;
case CBS_SPINLIST:
GetSpinBox (pData, dwStyle, &rect, &edit_box);
list_height = 0;
pData->spin_pace = 1;
pData->fastspin_pace = 5;
break;
case CBS_AUTOSPIN:
GetSpinBox (pData, dwStyle, &rect, &edit_box);
pData->spin_min = 0;
pData->spin_max = 100;
pData->spin_pace = 1;
pData->fastspin_pace = 5;
list_height = -1;
break;
default:
edit_box.left = rect.left;
edit_box.top = rect.top;
edit_box.right = rect.right - bmp_downarrow->bmWidth - INTER_EDIT_BUTTON;
edit_box.bottom = rect.bottom;
pData->SpinBmp = ARROWBMP_DOWN;
pData->DecSpinBox.left = rect.right - bmp_downarrow->bmWidth;
pData->DecSpinBox.top = (rect.bottom - bmp_downarrow->bmHeight)/2;
pData->DecSpinBox.right = rect.right;
pData->DecSpinBox.bottom = pData->DecSpinBox.top + bmp_downarrow->bmHeight;
pData->IncSpinBox.left = pData->DecSpinBox.left;
pData->IncSpinBox.top = pData->DecSpinBox.top;
pData->IncSpinBox.right = pData->DecSpinBox.right;
pData->IncSpinBox.bottom = pData->DecSpinBox.bottom;
list_height = (pCtrl->dwAddData > 0) ? pCtrl->dwAddData : DEF_LISTHEIGHT;
pData->ListBoxRect.left = rect.left;
pData->ListBoxRect.right = rect.right;
pData->ListBoxRect.top = rect.bottom;
pData->ListBoxRect.bottom = rect.bottom + list_height;
break;
}
tmpx = pData->ListBoxRect.right;
tmpy = pData->ListBoxRect.bottom;
ClientToScreen (hwnd, &tmpx, &tmpy);
if (tmpy > g_rcScr.bottom) {
pData->ListBoxRect.left = rect.left;
pData->ListBoxRect.right = rect.right;
pData->ListBoxRect.top = rect.top - list_height;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -