📄 listbox.c
字号:
{
RECT rcInv;
if (pos < pData->itemTop || pos > (pData->itemTop + pData->itemVisibles))
return;
GetClientRect (hwnd, &rcInv);
rcInv.top = (pos - pData->itemTop)*pData->itemHeight;
rcInv.bottom = rcInv.top + pData->itemHeight;
InvalidateRect (hwnd, &rcInv, fEBk);
}
static BOOL lstInvalidateUnderItem (HWND hwnd, PLISTBOXDATA pData, int pos)
{
RECT rcInv;
if (pos > (pData->itemTop + pData->itemVisibles))
return FALSE;
if (pos <= pData->itemTop) {
InvalidateRect (hwnd, NULL, TRUE);
return TRUE;
}
GetClientRect (hwnd, &rcInv);
lstGetItemsRect (pData, pos, -1, &rcInv);
if (rcInv.top < rcInv.bottom)
InvalidateRect (hwnd, &rcInv, TRUE);
return TRUE;
}
static PLISTBOXITEM lstGetItem (PLISTBOXDATA pData, int pos)
{
int i;
PLISTBOXITEM plbi;
plbi = pData->head;
for (i=0; i < pos && plbi; i++)
plbi = plbi->next;
return plbi;
}
static int lstFindItem (PLISTBOXDATA pData, int start, char* key, BOOL bExact)
{
PLISTBOXITEM plbi;
int keylen = strlen (key);
if (start >= (pData->itemCount - 1))
start = 0;
plbi = lstGetItem (pData, start);
while (plbi)
{
if (bExact && (keylen != strlen (plbi->key))) {
plbi = plbi->next;
start ++;
continue;
}
if (strncasecmp (key, plbi->key, keylen) == 0)
return start;
plbi = plbi->next;
start ++;
}
return LB_ERR;
}
static void lstOnDrawSListBoxItems (HDC hdc, DWORD dwStyle,
PLISTBOXDATA pData, int width)
{
PLISTBOXITEM plbi;
int i;
int x = 0, y = 0;
int offset;
RECT rc;
COLORREF bk;
plbi = lstGetItem (pData, pData->itemTop);
for (i = 0; plbi && i < (pData->itemVisibles + 1); i++) {
if (plbi->dwFlags & LBIF_SELECTED) {
SetBkColor (hdc, bk = BLUE);
SetTextColor (hdc, WHITE);
}
else {
SetBkColor (hdc, bk = WHITE);
SetTextColor (hdc, BLACK);
}
rc.left = 0;
rc.top = y;
rc.right = width;
rc.bottom = y + pData->itemHeight;
FastFillRect(hdc, &rc, bk);
if (dwStyle & LBS_CHECKBOX) {
x = LST_INTER_BMPTEXT;
if (plbi->dwFlags & LBIF_CHECKED)
offset = 0;
else if (plbi->dwFlags & LBIF_PARTCHECKED)
offset = LST_WIDTH_CHECKMARK << 1;
else
offset = LST_WIDTH_CHECKMARK;
#if 0 /* fix: no bitmap */
FillBoxWithBitmapPart (hdc,
x, y + ((pData->itemHeight - LST_HEIGHT_CHECKMARK)>>1),
LST_WIDTH_CHECKMARK, LST_HEIGHT_CHECKMARK,
0, 0,
&sg_bmpCheckMark,
offset, 0);
#endif
x += LST_WIDTH_CHECKMARK + LST_INTER_BMPTEXT;
}
#if 0 /* fix: no icon */
if (dwStyle & LBS_USEICON && plbi->dwData) {
DrawIcon (hdc,
x, y, pData->itemHeight, pData->itemHeight,
(HICON) plbi->dwData);
x += pData->itemHeight + LST_INTER_BMPTEXT;
}
#endif
/* jmt: should be SYSTEM_FIXED_FONT because of minigui's GetSysCharXXX() */
#if 0
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
#endif
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
TextOut (hdc, x+2, y, plbi->key,-1);
y += pData->itemHeight;
plbi = plbi->next;
}
}
static int lstSelectItem (DWORD dwStyle, PLISTBOXDATA pData, int newSel)
{
PLISTBOXITEM plbi, newItem;
int index;
newItem = lstGetItem (pData, newSel);
#if 1 /* jmt: fixed if no item added */
if (!newItem) return -1;
#endif
#ifdef _DEBUG
if (!newItem)
fprintf (stderr, "ASSERT failed: return value of lstGetItem"
" in lstSelectItem.\n");
#endif
if (dwStyle & LBS_MULTIPLESEL) {
newItem->dwFlags ^= LBIF_SELECTED;
return newSel;
}
index = 0;
plbi = pData->head;
while (plbi) {
if (plbi->dwFlags & LBIF_SELECTED) {
if (index != newSel) {
plbi->dwFlags &= ~LBIF_SELECTED;
newItem->dwFlags |= LBIF_SELECTED;
return index;
}
break;
}
plbi = plbi->next;
index ++;
}
newItem->dwFlags |= LBIF_SELECTED;
return -1;
}
static void lstDrawFocusRect (HDC hdc, PLISTBOXDATA pData, RECT* rc)
{
HGDIOBJ oldbrush,oldpen;
if (pData->itemHilighted < pData->itemTop
|| pData->itemHilighted > (pData->itemTop + pData->itemVisibles))
return;
if (pData->dwFlags & LBF_FOCUS) {
lstGetItemsRect (pData, pData->itemHilighted, pData->itemHilighted, rc);
#if 0
InflateRect (rc, -1, -1);
FocusRect (hdc, rc->left - 1, rc->top, rc->right, rc->bottom);
#else
oldbrush=SelectObject(hdc, GetStockObject(NULL_BRUSH));
oldpen=SelectObject(hdc, CreatePen(PS_SOLID, 1,
GetSysColor(COLOR_BTNHIGHLIGHT)));
#if 0
GdSetMode(MWMODE_XOR);
#endif
Rectangle (hdc, rc->left, rc->top, rc->right, rc->bottom);
#if 0
GdSetMode(MWMODE_SET);
#endif
SelectObject(hdc,oldbrush);
DeleteObject(SelectObject(hdc,oldpen));
#endif
}
}
static void lstCalcParams (const RECT* rcClient, PLISTBOXDATA pData)
{
#define RECTHP(prc) (prc->bottom - prc->top)
pData->itemVisibles = (RECTHP (rcClient)) / pData->itemHeight;
#if 1 /* test calculation of itemVisibles */
if( ((RECTHP (rcClient)) % pData->itemHeight) )
pData->itemVisibles++;
#endif
}
extern BOOL SetScrollPos (HWND hWnd, int iSBar, int iNewPos);
extern BOOL EnableScrollBar (HWND hWnd, int iSBar, BOOL bEnable);
static void lstSetVScrollInfo (HWND hwnd, PLISTBOXDATA pData, BOOL fRedraw)
{
SCROLLINFO si;
if (pData->itemVisibles >= pData->itemCount)
{
SetScrollPos (hwnd, SB_VERT, 0);
EnableScrollBar (hwnd, SB_VERT, FALSE);
return;
}
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = pData->itemCount - 1;
si.nMin = 0;
si.nPage = min (pData->itemVisibles, (pData->itemCount - pData->itemTop));
si.nPos = pData->itemTop;
SetScrollInfo (hwnd, SB_VERT, &si, fRedraw);
EnableScrollBar (hwnd, SB_VERT, TRUE);
}
LRESULT CALLBACK
ListboxCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
HWND pCtrl;
PLISTBOXDATA pData;
DWORD dwStyle;
pCtrl = hwnd;
dwStyle = pCtrl->style;
switch (message)
{
case WM_CREATE:
pData = (LISTBOXDATA*) GdMalloc (sizeof(LISTBOXDATA));
if (pData == NULL)
return -1;
pCtrl->userdata = (DWORD)pData;
if (!lstInitListBoxData (hwnd, pData, DEF_LB_BUFFER_LEN)) {
free (pData);
return -1;
}
break;
case WM_SIZE:
{
RECT rc;
pData = (PLISTBOXDATA)pCtrl->userdata;
GetClientRect(hwnd, &rc);
lstCalcParams (&rc, pData);
}
break;
case WM_DESTROY:
pData = (PLISTBOXDATA)pCtrl->userdata;
lstListBoxCleanUp (pData);
free (pData);
break;
case LB_RESETCONTENT:
pData = (PLISTBOXDATA)pCtrl->userdata;
lstResetListBoxContent (pData);
InvalidateRect (hwnd, NULL, TRUE);
break;
case LB_ADDSTRING:
case LB_INSERTSTRING:
{
char* string = NULL;
PLISTBOXITEMINFO plbii = NULL;
PLISTBOXITEM newItem;
int pos;
if (dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON) {
plbii = (PLISTBOXITEMINFO)lParam;
if (!plbii)
return LB_ERR;
string = plbii->string;
}
else {
string = (char*)lParam;
if (string == NULL || string [0] == '\0')
return LB_ERR;
}
pData = (PLISTBOXDATA)pCtrl->userdata;
newItem = lstAllocItem (pData);
if (!newItem) {
NotifyParent (hwnd, pCtrl->id, LBN_ERRSPACE);
return LB_ERRSPACE;
}
newItem->key = FixStrAlloc (strlen (string));
strcpy (newItem->key, string);
newItem->dwFlags = LBIF_NORMAL;
if (plbii) {
switch (plbii->cmFlag) {
case CMFLAG_CHECKED:
newItem->dwFlags |= LBIF_CHECKED;
break;
case CMFLAG_PARTCHECKED:
newItem->dwFlags |= LBIF_PARTCHECKED;
break;
}
if (dwStyle & LBS_USEICON)
newItem->dwData = (DWORD)plbii->hIcon;
else
newItem->dwData = 0L;
}
newItem->dwAddData = 0L;
if (message == LB_ADDSTRING)
pos = lstAddNewItem (dwStyle, pData, newItem, -1);
else
pos = lstAddNewItem (dwStyle, pData, newItem, (int)wParam);
lstInvalidateUnderItem (hwnd, pData, pos);
lstSetVScrollInfo (hwnd, pData, TRUE);
return pos;
}
break;
case LB_DELETESTRING:
{
PLISTBOXITEM removed;
int delete;
delete = (int)wParam;
pData = (PLISTBOXDATA)pCtrl->userdata;
removed = lstRemoveItem (pData, &delete);
if (removed) {
FreeFixStr (removed->key);
lstFreeItem (pData, removed);
pData->itemCount --;
if (pData->itemTop != 0
&& pData->itemCount <= pData->itemVisibles) {
pData->itemTop = 0;
InvalidateRect (hwnd, NULL, TRUE);
}
else {
lstInvalidateUnderItem (hwnd, pData, delete);
if (delete <= pData->itemTop) {
pData->itemTop --;
if (pData->itemTop < 0)
pData->itemTop = 0;
}
}
if (pData->itemHilighted >= pData->itemCount) {
pData->itemHilighted = pData->itemCount - 1;
if (pData->itemHilighted < 0)
pData->itemHilighted = 0;
}
if (pData->itemHilighted < pData->itemTop)
pData->itemHilighted = pData->itemTop;
if (pData->itemHilighted > ITEM_BOTTOM (pData))
pData->itemHilighted = ITEM_BOTTOM (pData);
lstSetVScrollInfo (hwnd, pData, TRUE);
}
}
break;
case LB_FINDSTRING:
if( *(char*)lParam == '\0' )
return LB_ERR;
pData = (PLISTBOXDATA)pCtrl->userdata;
return lstFindItem(pData, (int)wParam, (char*)lParam, FALSE);
case LB_FINDSTRINGEXACT:
if( *(char*)lParam == '\0' )
return LB_ERR;
pData = (PLISTBOXDATA)pCtrl->userdata;
return lstFindItem(pData, (int)wParam, (char*)lParam, TRUE);
case LB_SETTOPINDEX:
{
int newTop = (int) wParam;
pData = (PLISTBOXDATA)pCtrl->userdata;
if (newTop <0)
newTop = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -