⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 listbox.c

📁 microwindows最新源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1999, 2000, Wei Yongming. * Portions Copyright (c) 2000, 2005 Greg Haerr <greg@censoft.com> * * Listbox for Microwindows win32 api. *//***  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.**** 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**  Kevin Tseng     2000/05/26  gv          port to microwin        ported**  Greg Haerr      2000/06/15  Utah        3d look, bug fixes      Finished**  Kevin Tseng     2000/06/22  gv          port to mw-nanox        ported**  Kevin Tseng     2000/06/22  gv          fixed bug if no item    Finished**  Kevin Tseng     2000/08/08  gv          enable scrollbar(V)     porting**  Kevin Tseng     2000/08/10  gv          enable scrollbar(V)     ported**  Kevin Tseng     2000/08/10  gv          WM_CHAR, WM_KEYDOWN     ported** Gabriele Brugnoni 2003/09/16 Italy       Implemented WM_SETFONT  Finished** Gabriele Brugnoni 2003/09/16 Italy       Implemented LBS_USETABSTOPS  Finished** Gabriele Brugnoni 2003/09/29 Italy       Implemented WS_OWNERDRAW FIX and VAR**** TODO:** 1. Multiple columns support.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#define MWINCLUDECOLORS#include "windows.h"#include "wintern.h"#include "wintools.h"		/* Draw3dBox */#include "device.h"		/* GdGetTextSize *///  WM_SETFONT implementation#define GET_WND_FONT(h)			((HFONT)GetWindowLong(h, 0))#define SET_WND_FONT(h, f)		(SetWindowLong(h, 0, (LPARAM)(f)))#define ISOWNERDRAW(dwStyle)	((dwStyle & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) != 0)#define FixStrAlloc(n)	malloc((n)+1)#define FreeFixStr(p)	free(p)#define LBIF_NORMAL         0x0000L#define LBIF_SELECTED       0x0001L#define LBIF_CHECKED        0x0010L#define LBIF_PARTCHECKED    0x0020L#define LBIF_CHECKMARKMASK  0x00F0L#define CMFLAG_BLANK        0#define CMFLAG_CHECKED      1#define CMFLAG_PARTCHECKED  2typedef struct _LISTBOXITEMINFO{	int insPos;		/* insert position */	char *string;		/* item string */	int cmFlag;		/* check mark flag */	HICON hIcon;		/* handle of icon */} LISTBOXITEMINFO, *PLISTBOXITEMINFO;typedef struct _LISTBOXITEM{	char *key;		/* item sort key */	DWORD dwFlags;		/* item flags */	DWORD dwData;		/* item data */	DWORD dwAddData;	/* item additional data */	struct _LISTBOXITEM *next;	/* next item */} LISTBOXITEM, *PLISTBOXITEM;#define DEF_LB_BUFFER_LEN       5#define LBF_FOCUS               0x0001#define LBF_NOTHINGSELECTED	0x0002#define LBF_FOCUSRECT		0x0004#define LBF_USERMEASURE		0x0008typedef struct _LISTBOXDATA{	DWORD dwFlags;		/* listbox flags */	int itemCount;		/* items count */	int itemTop;		/* start display item */	int itemVisibles;	/* number of visible items */	int itemHilighted;	/* current hilighted item */	int itemHeight;		/* item height */	int hoffset;		/* offset for horiz scroll */	int hextent;		/* horizontal extent */	int nTabStops;		/* count of tabstops */	LPINT pTabStops;	/* array of tabstops */	LISTBOXITEM *head;	/* items linked list head */	int buffLen;		/* buffer length */	LISTBOXITEM *buffStart;	/* buffer start */	LISTBOXITEM *buffEnd;	/* buffer end */	LISTBOXITEM *freeList;	/* free list in buffer */} LISTBOXDATA, *PLISTBOXDATA;void ListboxControlCleanup();static LRESULT CALLBACKListboxCtrlProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);static void lstDrawFocusRect(HWND hwnd, HDC hdc, PLISTBOXDATA pData,			     BOOL bFocus);static PLISTBOXITEM lstGetItem(PLISTBOXDATA pData, int pos);#define ITEM_BOTTOM(x)  (x->itemTop + x->itemVisibles - 1)#define LST_WIDTH_CHECKMARK     11#define LST_HEIGHT_CHECKMARK    11#define LST_INTER_BMPTEXT       2int WINAPIMwRegisterListboxControl(HINSTANCE hInstance){	WNDCLASS wc;#if 0	static BITMAP sg_bmpCheckMark;	if (!LoadSystemBitmap(&sg_bmpCheckMark, "checkmark")) {		fprintf(stderr, "Load ListBox Check Mark Bitmap failure!\n");		return FALSE;	}#endif	wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;	wc.lpfnWndProc = (WNDPROC) ListboxCtrlProc;	wc.cbClsExtra = 0;	wc.cbWndExtra = 4;	// WM_SETFONT	wc.hInstance = hInstance;	wc.hIcon = NULL;	wc.hCursor = 0;		/*LoadCursor(NULL, IDC_ARROW); */	wc.hbrBackground = GetStockObject(WHITE_BRUSH);	wc.lpszMenuName = NULL;	wc.lpszClassName = "LISTBOX";	return RegisterClass(&wc);}voidListboxControlCleanup(){#if 0	UnloadBitmap(&sg_bmpCheckMark);#endif}static voidlbFillDrawitemstruct(HWND hwnd, HDC hdc, LPDRAWITEMSTRUCT lpDrw,		     LPRECT lpRc, UINT action, int id, PLISTBOXITEM plbi){	PLISTBOXDATA pData = (PLISTBOXDATA) hwnd->userdata;	if (plbi == NULL)		plbi = lstGetItem(pData, id);	lpDrw->CtlType = ODT_LISTBOX;	lpDrw->CtlID = GetDlgCtrlID(hwnd);	lpDrw->itemID = id;	lpDrw->itemAction = action;	lpDrw->itemState = 0;	if (plbi->dwFlags & LBIF_SELECTED)		lpDrw->itemState |= ODS_SELECTED;	if ((id == pData->itemHilighted) && (hwnd == GetFocus()))		lpDrw->itemState |= ODS_FOCUS;	if (!IsWindowEnabled(hwnd))		lpDrw->itemState |= ODS_DISABLED;	lpDrw->hwndItem = hwnd;	lpDrw->hDC = hdc;	lpDrw->rcItem = *lpRc;	lpDrw->itemData = plbi->dwData;}static BOOLlbAskMeasureItem(HWND hwnd, int id, int *ph){	MEASUREITEMSTRUCT ms;	BOOL res;	ms.CtlType = ODT_LISTBOX;	ms.CtlID = GetDlgCtrlID(hwnd);	ms.itemID = id;	if (id >= 0)		ms.itemData = SendMessage(hwnd, LB_GETITEMDATA, id, 0);	res = SendMessage(GetParent(hwnd), WM_MEASUREITEM, ms.CtlType,			  (LPARAM) & ms);	if (res) {		*ph = ms.itemHeight;	}	return res;}static LRESULTNotifyParent(HWND hwnd, int id, int code){	return SendMessage(GetParent(hwnd), WM_COMMAND,			   (WPARAM) MAKELONG(id, code), (LPARAM) hwnd);}static voidlstCalcHeight(HWND hwnd){	int xw, xh, xb;	PLISTBOXDATA pData = (PLISTBOXDATA) hwnd->userdata;	BOOL other = FALSE;	if (ISOWNERDRAW(GetWindowLong(hwnd, GWL_STYLE)))		other = lbAskMeasureItem(hwnd, -1, &pData->itemHeight);	if (!other) {		HDC hdc = GetDC(hwnd);#if MWCLIENT			/* nanox client */		GrSetGCFont(hdc->gc, hdc->font->fontid);		GrGetGCTextSize(hdc->gc, "X", 1, MWTF_ASCII, &xw, &xh, &xb);#else		SelectObject(hdc, GET_WND_FONT(hwnd));		GdSetFont(hdc->font->pfont);		GdGetTextSize(hdc->font->pfont, "X", 1, &xw, &xh, &xb,			      MWTF_ASCII);#endif		ReleaseDC(hwnd, hdc);		pData->itemHeight = xh + 1;	} else		pData->dwFlags |= LBF_USERMEASURE;}static BOOLlstInitListBoxData(HWND hwnd, LISTBOXDATA * pData, int len){	int i;	PLISTBOXITEM plbi;	RECT rc;	GetClientRect(hwnd, &rc);	memset(pData, 0, sizeof(LISTBOXDATA));	SET_WND_FONT(hwnd, GetStockObject(SYSTEM_FIXED_FONT));	lstCalcHeight(hwnd);	pData->itemHilighted = 0;	pData->dwFlags = LBF_NOTHINGSELECTED;	pData->hextent = rc.right;	pData->hoffset = 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 voidlstListBoxCleanUp(LISTBOXDATA * pData){	PLISTBOXITEM plbi;	PLISTBOXITEM next;	plbi = pData->head;	while (plbi) {		FreeFixStr(plbi->key);		next = plbi->next;		if (plbi < pData->buffStart || plbi > pData->buffEnd)			free(plbi);		plbi = next;	}	if (pData->pTabStops) {		free(pData->pTabStops);		pData->pTabStops = NULL;	}	free(pData->buffStart);}static voidlstResetListBoxContent(PLISTBOXDATA pData){	int i;	PLISTBOXITEM plbi, next;	pData->itemCount = 0;	pData->itemTop = 0;	pData->itemHilighted = 0;#if 0	pData->itemVisibles = 0;#endif	plbi = pData->head;	while (plbi) {		FreeFixStr(plbi->key);		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;}static PLISTBOXITEMlstAllocItem(PLISTBOXDATA pData){	PLISTBOXITEM plbi;	if (pData->freeList) {		plbi = pData->freeList;		pData->freeList = plbi->next;	} else		plbi = (PLISTBOXITEM) malloc(sizeof(LISTBOXITEM));	return plbi;}static voidlstFreeItem(PLISTBOXDATA pData, PLISTBOXITEM plbi){	if (plbi < pData->buffStart || plbi > pData->buffEnd)		free(plbi);	else {		plbi->next = pData->freeList;		pData->freeList = plbi;	}}static intlstAddNewItem(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 PLISTBOXITEMlstRemoveItem(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 voidlstGetItemsRect(HWND hwnd, PLISTBOXDATA pData, int start, int end, RECT * prc){	if (start < 0)		start = 0;	GetClientRect(hwnd, prc);	if (!(hwnd->style & LBS_OWNERDRAWVARIABLE) ||	    !(pData->dwFlags & LBF_USERMEASURE)) {		prc->top = (start - pData->itemTop) * pData->itemHeight;		if (end >= 0)			prc->bottom =				(end - pData->itemTop +				 1) * pData->itemHeight;	} else {		int i;		for (i = pData->itemTop; (i <= end) || (end < 0); i++) {			int h;			lbAskMeasureItem(hwnd, i, &h);			if (i < start)				prc->top += h;			else if (end < 0)				break;			if (i == end)				prc->bottom = prc->top + h;		}	}}static voidlstInvalidateItem(HWND hwnd, PLISTBOXDATA pData, int pos, BOOL fEBk){	RECT rcInv;	if (pos < pData->itemTop	    || pos > (pData->itemTop + pData->itemVisibles))		return;	lstGetItemsRect(hwnd, pData, pos, pos, &rcInv);	InvalidateRect(hwnd, &rcInv, fEBk);}static BOOLlstInvalidateUnderItem(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;	}	lstGetItemsRect(hwnd, pData, pos, -1, &rcInv);	if (rcInv.top < rcInv.bottom)		InvalidateRect(hwnd, &rcInv, FALSE);	return TRUE;}static PLISTBOXITEMlstGetItem(PLISTBOXDATA pData, int pos){	int i;	PLISTBOXITEM plbi;	plbi = pData->head;	for (i = 0; i < pos && plbi; i++)		plbi = plbi->next;	return plbi;}static intlstFindItem(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 voidlstOnDrawSListBoxItems(HWND hwnd, HDC hdc, DWORD dwStyle,		       PLISTBOXDATA pData, LPRECT pRcPaint){	PLISTBOXITEM plbi;	int i;	int x = 0, y = 0;	int offset;	RECT rc;	COLORREF bk;	int width;	GetClientRect(hwnd, &rc);	width = rc.right - rc.left;	plbi = lstGetItem(pData, pData->itemTop);	SelectObject(hdc, GET_WND_FONT(hwnd));	for (i = 0; plbi && i < (pData->itemVisibles + 1); i++) {		POINT centPt;		int itemHeight = pData->itemHeight;		if ((dwStyle & LBS_OWNERDRAWVARIABLE)) {			lbAskMeasureItem(hwnd, pData->itemTop + i, &itemHeight);		}		rc.left = 0;		rc.top = y;		rc.right = width;		rc.bottom = y + itemHeight;		centPt.x = width / 2;		centPt.y = y + itemHeight / 2;		/*  GB: ownerdraw  */		if (ISOWNERDRAW(dwStyle) && PtInRect(pRcPaint, centPt)) {			DRAWITEMSTRUCT drw;			lbFillDrawitemstruct(hwnd, hdc, &drw, &rc,					     ODA_DRAWENTIRE,					     pData->itemTop + i, plbi);			if (!SendMessage			    (GetParent(hwnd), WM_DRAWITEM, drw.CtlID,			     (LPARAM) & drw))				FastFillRect(hdc, &rc, WHITE);			if (pData->itemTop + i == pData->itemHilighted) {				if ((drw.itemState & ODS_FOCUS))					pData->dwFlags |= LBF_FOCUSRECT;				else					pData->dwFlags &= ~LBF_FOCUSRECT;			}		} else			/*  GB: draw only if in update region... */		if (PtInRect(pRcPaint, centPt)) {			if (plbi->dwFlags & LBIF_SELECTED) {				SetBkColor(hdc, bk = BLUE);				SetTextColor(hdc, WHITE);			} else {				SetBkColor(hdc, bk = WHITE);				SetTextColor(hdc, BLACK);			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -