📄 listbox.c
字号:
/*
* Copyright (C) 1999, 2000, Wei Yongming.
* Portions Copyright (c) 2000 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
**
** TODO:
** 1. Multiple columns support.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MWINCLUDECOLORS
#include "windows.h"
#include "wintools.h" /* Draw3dBox */
#include "device.h" /* GdGetTextSize */
#define FixStrAlloc(n) GdMalloc((n)+1)
#define FreeFixStr(p) GdFree(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 2
typedef 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
typedef 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 */
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 CALLBACK
ListboxCtrlProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
#define ITEM_BOTTOM(x) (x->itemTop + x->itemVisibles - 1)
#define LST_WIDTH_CHECKMARK 11
#define LST_HEIGHT_CHECKMARK 11
#define LST_INTER_BMPTEXT 2
int WINAPI MwRegisterListboxControl(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 = 0;
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);
}
void ListboxControlCleanup ()
{
#if 0
UnloadBitmap (&sg_bmpCheckMark);
#endif
}
static LRESULT NotifyParent (HWND hwnd, int id, int code)
{
return SendMessage (GetParent (hwnd), WM_COMMAND,
(WPARAM) MAKELONG (id, code), (LPARAM)hwnd);
}
static BOOL lstInitListBoxData (HWND hwnd,LISTBOXDATA* pData, int len)
{
int i, xw, xh, xb;
PLISTBOXITEM plbi;
HDC hdc;
memset (pData, 0, sizeof (LISTBOXDATA));
#if 0
pData->itemHeight = GetSysCharHeight ();
#else
hdc=GetDC(hwnd);
#if MWCLIENT /* nanox client */
GrSetGCFont(hdc->gc,hdc->font->fontid);
GrGetGCTextSize(hdc->gc,"X",1,
MWTF_ASCII,&xw,&xh,&xb);
#else
GdSetFont(hdc->font->pfont);
GdGetTextSize(hdc->font->pfont,"X",1,
&xw,&xh,&xb,MWTF_ASCII);
#endif
ReleaseDC(hwnd,hdc);
pData->itemHeight=xh + 1;
#endif
pData->itemHilighted = 0;
pData->dwFlags = LBF_NOTHINGSELECTED;
/* init item buffer. */
if (!(pData->buffStart = GdMalloc (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) {
FreeFixStr (plbi->key);
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;
#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 PLISTBOXITEM lstAllocItem (PLISTBOXDATA pData)
{
PLISTBOXITEM plbi;
if (pData->freeList) {
plbi = pData->freeList;
pData->freeList = plbi->next;
}
else
plbi = (PLISTBOXITEM) GdMalloc (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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -