📄 listbox.c
字号:
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 + ((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, itemHeight, itemHeight, (HICON) plbi->dwData); x += 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 if ((dwStyle & LBS_USETABSTOPS) != 0) TabbedTextOut(hdc, x + 2 - pData->hoffset, y, plbi->key, -1, pData->nTabStops, pData->pTabStops, -pData->hoffset); else TextOut(hdc, x + 2 - pData->hoffset, y, plbi->key, -1); if (pData->itemTop + i == pData->itemHilighted) { pData->dwFlags &= ~LBF_FOCUSRECT; lstDrawFocusRect(hwnd, hdc, pData, TRUE); } } y += itemHeight; plbi = plbi->next; }}static intlstSelectItem(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) EPRINTF("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 voidlstDrawFocusRect(HWND hwnd, HDC hdc, PLISTBOXDATA pData, BOOL bFocus){ DRAWITEMSTRUCT drw; RECT rc; BOOL painted = FALSE; DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE); if (pData->itemHilighted < pData->itemTop || pData->itemHilighted > (pData->itemTop + pData->itemVisibles)) return; lstGetItemsRect(hwnd, pData, pData->itemHilighted, pData->itemHilighted, &rc); if (ISOWNERDRAW(dwStyle)) { lbFillDrawitemstruct(hwnd, hdc, &drw, &rc, ODA_FOCUS, pData->itemHilighted, NULL); } rc.left++, rc.right--; if (bFocus) { if ((pData->dwFlags & LBF_FOCUS) && !(pData->dwFlags & LBF_FOCUSRECT)) { if (ISOWNERDRAW(dwStyle)) painted = SendMessage(GetParent(hwnd), WM_DRAWITEM, drw.CtlID, (LPARAM) & drw); if (!painted) DrawFocusRect(hdc, &rc); pData->dwFlags |= LBF_FOCUSRECT; } } else { if ((pData->dwFlags & LBF_FOCUSRECT)) { if (ISOWNERDRAW(dwStyle)) painted = SendMessage(GetParent(hwnd), WM_DRAWITEM, drw.CtlID, (LPARAM) & drw); if (!painted) DrawFocusRect(hdc, &rc); pData->dwFlags &= ~LBF_FOCUSRECT; } }}static voidlstCalcParams(HWND hwnd, RECT * rcClient, PLISTBOXDATA pData){#define RECTHP(prc) (prc->bottom - prc->top) RECT rc; if (rcClient == NULL) { rcClient = &rc; GetClientRect(hwnd, rcClient); } if (!(hwnd->style & LBS_OWNERDRAWVARIABLE)) pData->itemVisibles = (RECTHP(rcClient)) / pData->itemHeight; else { int i, y; for (i = 0, y = rcClient->top; (i < pData->itemCount) && (y <= rcClient->bottom); i++) { int h; lbAskMeasureItem(hwnd, i, &h); y += h; } if (i > 1) i--; pData->itemVisibles = i; }#if 0 /* 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 voidlstSetVScrollInfo(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);}static voidlstSetHScrollInfo(HWND hwnd, PLISTBOXDATA pData, BOOL fRedraw){ SCROLLINFO si; int maxoffs; RECT rc; GetClientRect(hwnd, &rc); maxoffs = pData->hextent - rc.right; if (maxoffs <= 0) { SetScrollPos(hwnd, SB_HORZ, 0); EnableScrollBar(hwnd, SB_HORZ, FALSE); } else { si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMax = maxoffs; si.nMin = 0; si.nPage = rc.right * 3 / 4; si.nPos = pData->hoffset; SetScrollInfo(hwnd, SB_HORZ, &si, fRedraw); EnableScrollBar(hwnd, SB_HORZ, TRUE); } if (fRedraw) InvalidateRect(hwnd, NULL, TRUE);}LRESULT CALLBACKListboxCtrlProc(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 *) malloc(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: pData = (PLISTBOXDATA) pCtrl->userdata; lstCalcParams(hwnd, NULL, 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); if ((dwStyle & LBS_OWNERDRAWVARIABLE)) lstCalcParams(hwnd, NULL, pData); 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); if ((dwStyle & LBS_OWNERDRAWVARIABLE)) lstCalcParams(hwnd, NULL, 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; else if (newTop > pData->itemCount - pData->itemVisibles) newTop = pData->itemCount - pData->itemVisibles; if (pData->itemTop != newTop) { pData->itemTop = newTop; if (pData->itemHilighted < pData->itemTop) pData->itemHilighted = pData->itemTop; if (pData->itemHilighted > ITEM_BOTTOM(pData)) pData->itemHilighted = ITEM_BOTTOM(pData); if ((dwStyle & LBS_OWNERDRAWVARIABLE)) lstCalcParams(hwnd, NULL, pData); lstSetVScrollInfo(hwnd, pData, TRUE); InvalidateRect(hwnd, NULL, TRUE); } } break; case LB_SETCURSEL: case LB_SETCARETINDEX: { int new = (int) wParam; int old, newTop; pData = (PLISTBOXDATA) pCtrl->userdata; if (new < 0 || new > pData->itemCount - 1) return LB_ERR; old = pData->itemHilighted; if (new >= 0 && new != old) { if (pData->itemCount - new >= pData->itemVisibles) newTop = new; else newTop = max(pData->itemCount - pData->itemVisibles, 0); pData->itemTop = newTop; pData->itemHilighted = new; if ((dwStyle & LBS_OWNERDRAWVARIABLE)) lstCalcParams(hwnd, NULL, pData); lstSetVScrollInfo(hwnd, pData, TRUE); } if (!(dwStyle & LBS_MULTIPLESEL)) lstSelectItem(dwStyle, pData, new); InvalidateRect(hwnd, NULL, TRUE); return old; } break; case LB_GETCOUNT: pData = (PLISTBOXDATA) pCtrl->userdata; return pData->itemCount; break; case LB_GETCURSEL: { PLISTBOXITEM plbi; int index = 0; pData = (PLISTBOXDATA) pCtrl->userdata; if (dwStyle & LBS_MULTIPLESEL) return pData->itemHilighted; plbi = pData->head; while (plbi) { if (plbi->dwFlags & LBIF_SELECTED) return index; index++; plbi = plbi->next; } return LB_ERR; } break; case LB_GETSELCOUNT: { int nSel; PLISTBOXITEM plbi; pData = (PLISTBOXDATA) pCtrl->userdata; nSel = 0; plbi = pData->head; while (plbi) { if (plbi->dwFlags & LBIF_SELECTED) nSel++; plbi = plbi->next; } return nSel; } break; case LB_GETTOPINDEX: pData = (PLISTBOXDATA) pCtrl->userdata; return pData->itemTop; break; case LB_GETCARETINDEX: pData = (PLISTBOXDATA) pCtrl->userdata; return pData->itemHilighted; break; case LB_GETTEXTLEN: { PLISTBOXITEM plbi; pData = (PLISTBOXDATA) pCtrl->userdata; plbi = lstGetItem(pData, (int) wParam); if (plbi) return strlen(plbi->key); else return LB_ERR; } break; case LB_GETTEXT: { PLISTBOXITEM plbi; pData = (PLISTBOXDATA) pCtrl->userdata; plbi = lstGetItem(pData, (int) wParam); if (plbi) strcpy((char *) lParam, plbi->key); else return LB_ERR; } break; case LB_SETTEXT: { PLISTBOXITEM plbi; char *newStr; pData = (PLISTBOXDATA) pCtrl->userdata; plbi = lstGetItem(pData, (int) wParam); if (plbi) { newStr = FixStrAlloc(strlen((char *) lParam)); if (newStr) { FreeFixStr(plbi->key); plbi->key = newStr; strcpy(plbi->key, (char *) lParam); lstInvalidateItem(hwnd, pData, (int) wParam, FALSE); } else return LB_ERR; } else return LB_ERR; } break; case LB_GETITEMDATA: { PLISTBOXITEM plbi; PLISTBOXITEMINFO plbii; pData = (PLISTBOXDATA) pCtrl->userdata; if (!(plbi = lstGetItem(pData, (int) wParam))) return LB_ERR; if (! (dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON)) { return plbi->dwData; } plbii = (PLISTBOXITEMINFO) lParam; if (!plbii) return LB_ERR; if (plbi->dwFlags & LBIF_CHECKED) plbii->cmFlag = CMFLAG_CHECKED; else if (plbi->dwFlags & LBIF_PARTCHECKED) plbii->cmFlag = CMFLAG_PARTCHECKED; else plbii->cmFlag = CMFLAG_BLANK; plbii->hIcon = (HICON) plbi->dwData; return LB_OKAY; } break; case LB_SETITEMDATA: { PLISTBOXITEM plbi; PLISTBOXITEMINFO plbii; pData = (PLISTBOXDATA) pCtrl->userdata; if (!(plbi = lstGetItem(pData, (int) wParam))) return LB_ERR; if (! (dwStyle & LBS_CHECKBOX || dwStyle & LBS_USEICON)) { plbi->dwData = (DWORD) lParam; return LB_OKAY; } plbii = (PLISTBOXITEMINFO) lParam; if (!plbii) return LB_ERR; plbi->dwFlags &= ~LBIF_CHECKMARKMASK; switch (plbii->cmFlag) { case CMFLAG_CHECKED: plbi->dwFlags |= LBIF_CHECKED; break; case CMFLAG_PARTCHECKED: plbi->dwFlags |= LBIF_PARTCHECKED; break; } if (dwStyle & LBS_USEICON) plbi->dwData = (DWORD) plbii->hIcon; else plbi->dwData = 0; lstInvalidateItem(hwnd, pData, (int) wParam, FALSE); return LB_OKAY; } break; case LB_GETITEMADDDATA: { PLISTBOXITEM plbi; pData = (PLISTBOXDATA) pCtrl->userdata; if (!(plbi = lstGetItem(pData, (int) wParam))) return LB_ERR; return plbi->dwAddData; } break; case LB_SETITEMADDDATA: { PLISTBOXITEM plbi; pData = (PLISTBOXDATA) pCtrl->userdata; if (!(plbi = lstGetItem(pData, (int) wParam))) return LB_ERR; plbi->dwAddData = (DWORD) lParam; return LB_OKAY; } break; case LB_GETCHECKMARK: { PLISTBOXITEM plbi; if (!(dwStyle & LBS_CHECKBOX)) return LB_ERR; pData = (PLISTBOXDATA) pCtrl->userdata; if (!(plbi = lstGetItem(pData, (int) wParam))) return LB_ERR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -