📄 listbox.c
字号:
// $Id: listbox.c,v 1.7 2000/11/17 07:02:01 ymwei Exp $//// listbox.c: the List Box Control module.//// Copyright (C) 1999, 2000, Wei Yongming.// // Current maintainer: Wei Yongming.///*** This library is free software; you can redistribute it and/or** modify it under the terms of the GNU Library General Public** License as published by the Free Software Foundation; either** version 2 of the License, or (at your option) any later version.**** This library 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** Library General Public License for more details.**** You should have received a copy of the GNU Library General Public** License along with this library; if not, write to the Free** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,** MA 02111-1307, USA*//*** Alternatively, the contents of this file may be used under the terms ** of the Mozilla Public License (the "MPL License") in which case the** provisions of the MPL License are applicable instead of those above.*/// Note:// Although there was a version by Zhao Jianghua, this version of// LISTBOX control is written by Wei Yongming from scratch.//// Create date: 1999/8/31//// Modify records://// Who When Where For What Status//-----------------------------------------------------------------------------// Wei Yongming 1999/10/18 Tsinghua Item Additional Data Finished// Wei Yongming 1999/10/31 Tsinghua Space bar for checkmark Finished// Wei Yongming 1999/10/31 Tsinghua Character match item Finished// Wei Yongming 1999/11/07 Tsinghua Character match item Bug fixing// WEI Yongming 2000/01/20 Tsinghua Thumb dragging Finished// WEI Yongming 2000/02/24 Tsinghua Add MPL License Finished//// TODO:// 1. Multiple columns support.//#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <semaphore.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"#include "ctrlmisc.h"#include "listbox.h"#ifndef lintstatic char fileid[] = "$Id: listbox.c,v 1.7 2000/11/17 07:02:01 ymwei Exp $";#endif#define _USE_FIXSTR 1#define ITEM_BOTTOM(x) (x->itemTop + x->itemVisibles - 1)#define LST_WIDTH_CHECKMARK 11#define LST_HEIGHT_CHECKMARK 11#define LST_INTER_BMPTEXT 2static BITMAP sg_bmpCheckMark;BOOL RegisterListboxControl (void){ WNDCLASS WndClass; if (!LoadSystemBitmap (&sg_bmpCheckMark, "checkmark")) { fprintf (stderr, "Load ListBox Check Mark Bitmap failure!\n"); return FALSE; } WndClass.spClassName = "listbox"; WndClass.dwStyle = 0; WndClass.hCursor = GetSystemCursor (0); WndClass.iBkColor = PIXEL_lightwhite; WndClass.WinProc = ListboxCtrlProc; return AddNewControlClass (&WndClass) == ERR_OK;}void ListboxControlCleanup (void){ UnloadBitmap (&sg_bmpCheckMark); return;}static BOOL lstInitListBoxData (LISTBOXDATA* pData, int len){ int i; PLISTBOXITEM plbi; pData->itemHeight = GetSysCharHeight (); pData->itemHilighted = 0; // init item buffer. if (!(pData->buffStart = malloc (len * sizeof (LISTBOXITEM)))) return FALSE; pData->buffLen = len; pData->buffEnd = pData->buffStart + len; pData->freeList = pData->buffStart; plbi = pData->freeList; for (i = 0; i < len - 1; i++) { plbi->next = plbi + 1; plbi ++; } plbi->next = NULL; return TRUE;}static void lstListBoxCleanUp (LISTBOXDATA* pData){ PLISTBOXITEM plbi; PLISTBOXITEM next; plbi = pData->head; while (plbi) {#if _USE_FIXSTR FreeFixStr (plbi->key);#else free (plbi->key);#endif next = plbi->next; if (plbi < pData->buffStart || plbi > pData->buffEnd) free (plbi); plbi = next; } free (pData->buffStart);}static void lstResetListBoxContent (PLISTBOXDATA pData){ int i; PLISTBOXITEM plbi, next; pData->itemCount = 0; pData->itemTop = 0; pData->itemHilighted = 0; plbi = pData->head; while (plbi) {#if _USE_FIXSTR FreeFixStr (plbi->key);#else free (plbi->key);#endif next = plbi->next; if (plbi < pData->buffStart || plbi > pData->buffEnd) free (plbi); plbi = next; } pData->head = NULL; pData->freeList = pData->buffStart; plbi = pData->freeList; for (i = 0; i < pData->buffLen - 1; i++) { plbi->next = plbi + 1; plbi ++; } plbi->next = NULL; return;}static PLISTBOXITEM lstAllocItem (PLISTBOXDATA pData){ PLISTBOXITEM plbi; if (pData->freeList) { plbi = pData->freeList; pData->freeList = plbi->next; } else plbi = (PLISTBOXITEM) malloc (sizeof (LISTBOXITEM)); return plbi;}static void lstFreeItem (PLISTBOXDATA pData, PLISTBOXITEM plbi){ if (plbi < pData->buffStart || plbi > pData->buffEnd) free (plbi); else { plbi->next = pData->freeList; pData->freeList = plbi; }}static int lstAddNewItem (DWORD dwStyle, PLISTBOXDATA pData, PLISTBOXITEM newItem, int pos){ PLISTBOXITEM plbi; PLISTBOXITEM insPosItem = NULL; int insPos = 0; newItem->next = NULL; if (!pData->head) insPosItem = NULL; else if (dwStyle & LBS_SORT) { plbi = pData->head; if (strcmp (newItem->key, plbi->key) < 0) { insPosItem = NULL; insPos = 0; } else { while (plbi->next) { if (strcmp (newItem->key, plbi->next->key) <= 0) break; plbi = plbi->next; insPos ++; } insPosItem = plbi; } } else { plbi = pData->head; if (pos < 0) { while (plbi->next) { plbi = plbi->next; insPos ++; } insPosItem = plbi; } else if (pos > 0) { int index = 0; while (plbi->next) { if (pos == index) break; plbi = plbi->next; index ++; insPos ++; } insPosItem = plbi; } } if (insPosItem) { plbi = insPosItem->next; insPosItem->next = newItem; newItem->next = plbi; insPos ++; } else { plbi = pData->head; pData->head = newItem; newItem->next = plbi; } pData->itemCount ++; return insPos;}static PLISTBOXITEM lstRemoveItem (PLISTBOXDATA pData, int* pos){ int index = 0; PLISTBOXITEM plbi, prev; if (!pData->head) return NULL; if (*pos < 0) { prev = pData->head; plbi = pData->head; while (plbi->next) { prev = plbi; plbi = plbi->next; index ++; } if (plbi == pData->head) { pData->head = pData->head->next; *pos = 0; return plbi; } else { prev->next = plbi->next; *pos = index; return plbi; } } else if (*pos == 0) { plbi = pData->head; pData->head = plbi->next; return plbi; } else { index = 0; prev = pData->head; plbi = pData->head; while (plbi->next) { if (*pos == index) break; prev = plbi; plbi = plbi->next; index ++; } if (plbi == pData->head) { pData->head = pData->head->next; *pos = 0; return plbi; } else { prev->next = plbi->next; *pos = index; return plbi; } } return NULL;}static void lstGetItemsRect (PLISTBOXDATA pData, int start, int end, RECT* prc){ if (start < 0) start = 0; prc->top = (start - pData->itemTop)*pData->itemHeight; if (end >= 0) prc->bottom = (end - pData->itemTop + 1)*pData->itemHeight;}static void lstInvalidateItem (HWND hwnd, PLISTBOXDATA pData, int pos, BOOL fEBk){ 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; else if (start < 0) 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; plbi = lstGetItem (pData, pData->itemTop); for (i = 0; plbi && i < (pData->itemVisibles + 1); i++) { if (plbi->dwFlags & LBIF_SELECTED) { SetBrushColor (hdc, PIXEL_darkblue); SetBkColor (hdc, PIXEL_darkblue); SetTextColor (hdc, PIXEL_lightwhite); } else { SetBrushColor (hdc, PIXEL_lightwhite); SetBkColor (hdc, PIXEL_lightwhite); SetTextColor (hdc, PIXEL_black); } FillBox (hdc, 0, y, width, pData->itemHeight); 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; FillBoxWithBitmapPart (hdc, x, y + ((pData->itemHeight - LST_HEIGHT_CHECKMARK)>>1), LST_WIDTH_CHECKMARK, LST_HEIGHT_CHECKMARK, 0, 0, &sg_bmpCheckMark, offset, 0); x += LST_WIDTH_CHECKMARK + LST_INTER_BMPTEXT; } if (dwStyle & LBS_USEICON && plbi->dwData) { DrawIcon (hdc, x, y, pData->itemHeight, pData->itemHeight, (HICON) plbi->dwData); x += pData->itemHeight + LST_INTER_BMPTEXT; } TextOut (hdc, x, y, plbi->key); y += pData->itemHeight; plbi = plbi->next; }}static int lstSelectItem (DWORD dwStyle, 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 (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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -