📄 listbox.c
字号:
plbi = plbi->next;
start ++;
continue;
}
if (pData->str_cmp (key, plbi->key, keylen) == 0)
return start;
plbi = plbi->next;
start ++;
}
return LB_ERR;
}
static void lstOnDrawSListBoxItems (HWND hWnd, HDC hdc,
PLISTBOXDATA pData, int width)
{
DWORD dwStyle = GetWindowStyle (hWnd);
PLISTBOXITEM plbi;
int i;
int x = 0, y = 0;
int offset;
plbi = lstGetItem (pData, pData->itemTop);
for (i = 0; plbi && i < (pData->itemVisibles + 1); i++) {
if (plbi->dwFlags & LBIF_SELECTED) {
SetBkMode (hdc, BM_OPAQUE);
SetBkColor (hdc, GetWindowElementColorEx (hWnd, BKC_HILIGHT_NORMAL));
SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_HILIGHT_NORMAL));
SetBrushColor (hdc, GetWindowElementColorEx (hWnd, BKC_HILIGHT_NORMAL));
FillBox (hdc, 0, y, width, pData->itemHeight);
}
else {
SetBkMode (hdc, BM_TRANSPARENT);
SetTextColor (hdc, GetWindowElementColorEx (hWnd, FGC_CONTROL_NORMAL));
}
x = LST_INTER_BMPTEXT;
if (dwStyle & LBS_CHECKBOX) {
if (plbi->dwFlags & LBIF_CHECKED)
offset = 0;
else if (plbi->dwFlags & LBIF_PARTCHECKED)
offset = LST_WIDTH_CHECKMARK << 1;
else
offset = LST_WIDTH_CHECKMARK;
FillBoxWithBitmapPart (hdc,
x, y + ((pData->itemHeight - LST_HEIGHT_CHECKMARK)>>1),
LST_WIDTH_CHECKMARK, LST_HEIGHT_CHECKMARK,
0, 0,
CHECKMARK_BMP,
offset, 0);
x += LST_WIDTH_CHECKMARK + LST_INTER_BMPTEXT;
}
if (dwStyle & LBS_USEICON && plbi->dwImage) {
if (plbi->dwFlags & LBIF_USEBITMAP) {
FillBoxWithBitmap (hdc, x, y, 0, pData->itemHeight,
(PBITMAP) plbi->dwImage);
x += ((PBITMAP)(plbi->dwImage))->bmWidth;
}
else {
int width;
DrawIcon (hdc, x, y, 0, pData->itemHeight,
(HICON) plbi->dwImage);
GetIconSize ((HICON) plbi->dwImage, &width, NULL);
x += width;
}
x += LST_INTER_BMPTEXT;
}
{
FONTMETRICS fm;
GetFontMetrics (GetCurFont (hdc), &fm);
TextOut (hdc, x, y + ((pData->itemHeight - fm.font_height) >> 1), plbi->key);
}
y += pData->itemHeight;
plbi = plbi->next;
}
}
static int lstSelectItem (HWND hwnd, PLISTBOXDATA pData, int newSel)
{
PLISTBOXITEM plbi, newItem;
int index;
newItem = lstGetItem (pData, newSel);
#ifdef _DEBUG
if (!newItem)
fprintf (stderr, "ASSERT failed: return value of lstGetItem"
" in lstSelectItem.\n");
#endif
if (GetWindowStyle (hwnd) & 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 int lstCancelSelected (HWND hwnd, PLISTBOXDATA pData)
{
PLISTBOXITEM plbi;
int index;
index = 0;
plbi = pData->head;
while (plbi) {
if (plbi->dwFlags & LBIF_SELECTED) {
RECT rc;
plbi->dwFlags &= ~LBIF_SELECTED;
lstGetItemsRect (pData, index, index, &rc);
InvalidateRect (hwnd, &rc, TRUE);
return index;
}
plbi = plbi->next;
index ++;
}
return -1;
}
static void lstDrawFocusRect (HWND hwnd, HDC hdc, PLISTBOXDATA pData)
{
RECT rc;
if (pData->itemHilighted < pData->itemTop
|| pData->itemHilighted > (pData->itemTop + pData->itemVisibles))
return;
if (pData->dwFlags & LBF_FOCUS) {
GetClientRect (hwnd, &rc);
lstGetItemsRect (pData,
pData->itemHilighted, pData->itemHilighted,
&rc);
InflateRect (&rc, -1, -1);
#ifndef _GRAY_SCREEN
SetPenColor (hdc, PIXEL_lightwhite);
FocusRect (hdc, rc.left, rc.top, rc.right, rc.bottom);
#endif
}
}
static void lstCalcParams (const RECT* rcClient, PLISTBOXDATA pData)
{
pData->itemVisibles = (RECTHP (rcClient)) / pData->itemHeight;
}
static void change_scrollbar (HWND hwnd, PLISTBOXDATA pData, BOOL bShow)
{
if (pData->sbPolicy == SB_POLICY_ALWAYS)
EnableScrollBar (hwnd, SB_VERT, bShow);
else if (pData->sbPolicy == SB_POLICY_AUTOMATIC)
ShowScrollBar (hwnd, SB_VERT, bShow);
}
static void lstSetVScrollInfo (HWND hwnd, PLISTBOXDATA pData, BOOL fRedraw)
{
SCROLLINFO si;
if (pData->sbPolicy == SB_POLICY_NEVER) {
ShowScrollBar (hwnd, SB_VERT, FALSE);
return;
}
if (pData->itemVisibles >= pData->itemCount) {
SetScrollPos (hwnd, SB_VERT, 0);
change_scrollbar (hwnd, pData, FALSE);
return;
}
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = pData->itemCount - 1;
si.nMin = 0;
#if 0
si.nPage = MIN (pData->itemVisibles, (pData->itemCount - pData->itemTop));
#else
si.nPage = MIN (pData->itemVisibles, pData->itemCount);
#endif
si.nPos = pData->itemTop;
SetScrollInfo (hwnd, SB_VERT, &si, fRedraw);
EnableScrollBar (hwnd, SB_VERT, TRUE);
change_scrollbar (hwnd, pData, TRUE);
}
static int ListboxCtrlProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PCONTROL pCtrl;
PLISTBOXDATA pData;
DWORD dwStyle;
#if _USE_FIXSTR
int len;
#endif
pCtrl = Control(hwnd);
dwStyle = pCtrl->dwStyle;
switch (message)
{
case MSG_CREATE:
pData = (LISTBOXDATA*) calloc (1, sizeof(LISTBOXDATA));
if (pData == NULL)
return -1;
pCtrl->dwAddData2 = (DWORD)pData;
if (!lstInitListBoxData (hwnd, pCtrl, pData, DEF_LB_BUFFER_LEN)) {
free (pData);
return -1;
}
lstSetVScrollInfo (hwnd, pData, FALSE);
break;
case MSG_SIZECHANGED:
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
lstCalcParams ((const RECT*)lParam, pData);
break;
case MSG_DESTROY:
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
lstListBoxCleanUp (pData);
free (pData);
break;
case LB_SETSTRCMPFUNC:
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
if (pData->itemCount == 0 && lParam) {
pData->str_cmp = (STRCMP)lParam;
return LB_OKAY;
}
return LB_ERR;
case LB_RESETCONTENT:
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
lstResetListBoxContent (pData);
InvalidateRect (hwnd, NULL, TRUE);
return 0;
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->dwAddData2;
newItem = lstAllocItem (pData);
if (!newItem) {
if (dwStyle & LBS_NOTIFY)
NotifyParent (hwnd, pCtrl->id, LBN_ERRSPACE);
return LB_ERRSPACE;
}
#if _USE_FIXSTR
len = strlen (string);
newItem->key = FixStrAlloc (len);
if (!newItem->key) {
lstFreeItem (pData, newItem);
return LB_ERRSPACE;
}
if (len > 0)
strcpy (newItem->key, string);
#else
newItem->key = strdup (string);
if (!newItem->key) {
lstFreeItem (pData, newItem);
return LB_ERRSPACE;
}
#endif
newItem->dwFlags = LBIF_NORMAL;
if (plbii) {
if (plbii->cmFlag & CMFLAG_CHECKED)
newItem->dwFlags |= LBIF_CHECKED;
else if (plbii->cmFlag & CMFLAG_PARTCHECKED)
newItem->dwFlags |= LBIF_PARTCHECKED;
if (plbii->cmFlag & IMGFLAG_BITMAP)
newItem->dwFlags |= LBIF_USEBITMAP;
if (dwStyle & LBS_USEICON)
newItem->dwImage = (DWORD)plbii->hIcon;
else
newItem->dwImage = 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;
}
case LB_DELETESTRING:
{
PLISTBOXITEM removed;
int delete;
delete = (int)wParam;
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
removed = lstRemoveItem (pData, &delete);
if (removed) {
#if _USE_FIXSTR
FreeFixStr (removed->key);
#else
free (removed->key);
#endif
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);
return LB_OKAY;
}
return LB_ERR;
}
case LB_FINDSTRING:
if( *(char*)lParam == '\0' )
return LB_ERR;
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
return lstFindItem(pData, (int)wParam, (char*)lParam, FALSE);
case LB_FINDSTRINGEXACT:
if( *(char*)lParam == '\0' )
return LB_ERR;
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
return lstFindItem(pData, (int)wParam, (char*)lParam, TRUE);
case LB_SETTOPINDEX:
{
int newTop = (int) wParam;
pData = (PLISTBOXDATA)pCtrl->dwAddData2;
if (newTop <0)
newTop = 0;
else if (newTop > pData->itemCount - pData->itemVisibles)
newTop = pData->itemCount - pData->itemVisibles;
if (pData->itemTop != newTop) {
pData->itemTop = newTop;
if (pData->itemHilighted < pData->itemTop)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -