drop-down-edit-box.zc
来自「实现树形结构」· ZC 代码 · 共 579 行
ZC
579 行
//[of]:license
//[c]Code Browser - a folding text editor for programmers
//[c]Copyright (C) 2003-07 Marc Kerbiquet
//[c]
//[c]This program is free software; you can redistribute it and/or modify
//[c]it under the terms of the GNU General Public License as published by
//[c]the Free Software Foundation; either version 2 of the License, or
//[c](at your option) any later version.
//[c]
//[c]This program is distributed in the hope that it will be useful,
//[c]but WITHOUT ANY WARRANTY; without even the implied warranty of
//[c]MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//[c]GNU General Public License for more details.
//[c]
//[c]You should have received a copy of the GNU General Public License
//[c]along with this program; if not, write to the Free Software
//[c]Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//[cf]
//[of]:imports
import "base/types"
import "base/memory-allocator"
import "text/string"
import "text/vector-of-strings"
import "text/string-buffer"
//[c]
import "graphics/geometry"
import "graphics/graphics"
import "user/box"
import "toolbox/clipboard"
//[c]
import "win32/windows"
//[cf]
//[c]
//[of]:drop down edit box
//[of]:type
public struct drop down edit box : local box
private
edit hwnd : HWND
edit proc : WNDPROC
starting position: DWORD
ending position: DWORD
content: string
end
//[cf]
//[of]:instance creation
//[of]:new drop down edit box (parent)
public func new drop down edit box (parent: box)
equ s = sizeof local drop down edit box
def e = allocate memory (s): drop down edit box
initialize (e, parent)
return e
end
//[cf]
//[cf]
//[of]:text
//[of]:text
//[c]Returns the content of the drop down edit box
//[c]
public func text (m: drop down edit box)
// update the member attribute from the control
def stream := temp string buffer
def size = GetWindowTextLengthA (hwnd (m))
def p = buffer (stream, size)
GetWindowTextA (hwnd (m), p, size+1)
set content (m, as string (stream))
release (stream)
return content (m)
end
//[cf]
//[of]:set text (text)
//[c]Changes the content of the drop down edit box
//[c]
public func set text (m: drop down edit box, text: string)
set content (m, text)
set window text (m, text)
reset selection save (m)
on value changed (m)
end
//[cf]
//[cf]
//[of]:selection
//[of]:select (starting pos, ending pos)
//[c]Selects a part of the text
//[c]
public func select (m: drop down edit box, starting pos: int, ending pos: int)
send message (m, CB_SETEDITSEL, 0:WPARAM, MAKELPARAM(starting pos, ending pos))
end
//[cf]
//[of]:is selection empty
//[c]Tests if the current selection is empty
//[c]
public func is selection empty (m: drop down edit box)
def l = send message (m, CB_GETEDITSEL): DWORD
return HIWORD (l) == LOWORD (l)
end
//[cf]
//[cf]
//[of]:list
//[of]:size of list
public func size of list (m: drop down edit box)
return send message (m, CB_GETCOUNT): int
end
//[cf]
//[of]:set list (vector)
//[c]
public func set list (m: drop down edit box, v: vector of strings)
each (v) ? s
send message (m, CB_ADDSTRING, 0:WPARAM, s:LPARAM)
end
end
//[cf]
//[cf]
//[c]
//[of]:restricted
//[of]:initialize (parent)
public func initialize (m: drop down edit box, parent: box)
initialize (super (m), parent)
class (m) = drop down edit box class
starting position (m) = 0
ending position (m) = 0
content (m) = empty string
create managed window ex (
m,
get ex style (m),
"combobox",
nil,
get style (m),
m:HMENU,
nil)
set edit font (m)
// Capture the messages of the edit control
def edit hwnd = FindWindowExA (hwnd (m), nil, "edit", nil)
SetWindowLongA (edit hwnd, GWL_USERDATA, m:LONG)
edit proc (m) = GetWindowLongA (edit hwnd, GWL_WNDPROC):WNDPROC
SetWindowLongA (edit hwnd, GWL_WNDPROC, ^edit window proc (HWND, UINT, WPARAM, LPARAM):LONG)
edit hwnd (m) = edit hwnd
end
//[cf]
//[c]
//[of]:actual cut
public func actual cut (m: drop down edit box)
default window proc (m, WM_CUT, 0, 0)
return true
end
//[cf]
//[of]:actual copy
public func actual copy (m: drop down edit box)
return default window proc (m, WM_COPY, 0, 0) > 0
end
//[cf]
//[of]:actual paste
public func actual paste (m: drop down edit box)
default window proc (m, WM_PASTE, 0, 0)
return true
end
//[cf]
//[of]:actual clear
public func actual clear (m: drop down edit box)
default window proc (m, WM_CLEAR, 0, 0)
return true
end
//[cf]
//[of]:actual select all
public func actual select all (m: drop down edit box)
select (m, 0, -1)
return true
end
//[cf]
//[of]:actual can copy
public func actual can copy (m: drop down edit box)
return ~ is selection empty (m)
end
//[cf]
//[of]:actual can paste
public func actual can paste (m: drop down edit box)
if is read only (m)
return false
end
def can paste = false
each clipboard format ? fmt
if fmt == CF_TEXT
can paste = true
break
end
end
return can paste
end
//[cf]
//[of]:actual can clear
func actual can clear (m: drop down edit box)
return ~ is read only (m) && ~ is selection empty (m)
end
//[cf]
//[of]:actual release
public func actual release (m: drop down edit box)
delete (content (m))
actual release (super (m))
end
//[cf]
//[of]:actual compute min size
public func actual compute min size (m: drop down edit box)
def a: local area
def canvas: local canvas
initialize (canvas)
set font (canvas, edit font (style (m)))
text extent (canvas, "X", 1, a)
release (canvas)
def rect : local LPRECT
left (rect) = 0
top (rect) = 0
right (rect) = w (a)
bottom (rect) = h (a)
AdjustWindowRectEx (rect, get style (m), 0, get ex style (m))
def w = 120
def h = bottom (rect) - top (rect)
if edit border (style (m)) <> border none
h += 2
end
set min size(m, w, h)
end
//[cf]
//[of]:actual set read only (ro)
public func actual set read only (m: drop down edit box, ro: bool)
// exit if unchanged
if read only (m) == ro
return
end
//send message (m, EM_SETREADONLY, ro:BOOL:WPARAM, 0)
read only (m) = ro
end
//[cf]
//[of]:actual move (rectangle, repaint)
//[c]Move the box
//[c]
//[c]The position of a box should be changed only by its parent from
//[c]the on size or adjust event.
//[c]
public func actual move (m: drop down edit box, r: rectangle, repaint: bool)
MoveWindow (
hwnd (m),
x (r),
y (r),
w (r),
100,
BOOL (repaint))
end
//[cf]
//[c]
//[of]:handle focus
public func handle focus (m: drop down edit box, e: event)
select all (m)
return handle focus (super (m), e)
end
//[cf]
//[cf]
//[of]:private
//[of]:edit window proc
//[c]
public [call="__stdcall"] func edit window proc (
hwnd: HWND,
msg: UINT,
wParam: WPARAM,
lParam: LPARAM)
def m = box from hwnd (hwnd): drop down edit box
def res = edit window proc (m, msg, wParam, lParam)
switch msg
case WM_SETFOCUS,
WM_KILLFOCUS,
WM_KEYDOWN, WM_SYSKEYDOWN,
WM_LBUTTONDOWN,
WM_MBUTTONDOWN,
WM_RBUTTONDOWN,
WM_LBUTTONUP,
WM_MBUTTONUP,
WM_RBUTTONUP,
WM_LBUTTONDBLCLK,
WM_MBUTTONDBLCLK,
WM_RBUTTONDBLCLK,
WM_MOUSEMOVE
check selection changed (m)
end
return res
end
//[c]
public func edit window proc (
m: drop down edit box,
msg: UINT,
wParam: WPARAM,
lParam: LPARAM)
switch msg
case WM_SETFOCUS
if on focus (m)
return 0
end
case WM_KILLFOCUS
if on blur (m)
return 0
end
case WM_KEYDOWN, WM_SYSKEYDOWN
equ key = wParam: int
if (key == VK_ESCAPE || key == VK_RETURN) && is dropped down (m)
last key event processed (m) = true
show drop down (m, false)
return 0
end
def processed = on key down (m, key event (key down event type, key, get key flags))
last key event processed (m) = processed
if processed
return 0
end
case WM_CHAR, WM_SYSCHAR
if last key event processed (m)
last key event processed (m) = false
return 0
end
if on char (m, char event (wParam: TCHAR, get key flags))
return 0
end
end
return CallWindowProcA (edit proc (m), edit hwnd (m), msg, wParam, lParam)
end
//[cf]
//[c]
//[of]:wm key down
private func wm key down (m: drop down edit box, msg: UINT, wParam: WPARAM, lParam: LPARAM)
wm key down (super (m), msg, wParam, lParam)
check selection changed (m)
return 0
end
//[cf]
//[of]:wm char
private func wm char (m: drop down edit box, msg: UINT, wParam: WPARAM, lParam: LPARAM)
wm char (super (m), msg, wParam, lParam)
check selection changed (m)
return 0
end
//[cf]
//[of]:wm size
//[c]It seems windows selects the text when resizing.
//[c]
//[c]This method save and restore the selection when resizing.
//[c]
func wm size (
m: drop down edit box,
msg: UINT,
wParam: WPARAM,
lParam: LPARAM)
// Save selection
def s: [1] DWORD
def e: [1] DWORD
send message (m, CB_GETEDITSEL, s:WPARAM, e:LPARAM)
// Save content
def stream := temp string buffer
def size = GetWindowTextLengthA (hwnd (m))
def p = buffer (stream, size)
GetWindowTextA (hwnd (m), p, size+1)
// Call parent proc
def res = wm size (super (m), msg, wParam, lParam)
// Restore content
SetWindowTextA (hwnd (m), p)
release (stream)
// Restore selection
send message (m, CB_SETEDITSEL, 0, (e[] << 16 | s[]):LPARAM)
return res
end
//[cf]
//[of]:actual win command (code)
private func actual win command (m: drop down edit box, notify code: WORD)
if notify code == CBN_EDITCHANGE:WORD
on value changed (m)
check selection changed (m)
elsif notify code == CBN_SELCHANGE:WORD
// Force updating text before sending events
def index = send message (m, CB_GETCURSEL)
if index <> CB_ERR
send message (m, CB_SETCURSEL, index)
end
on value changed (m)
check selection changed (m)
end
end
//[cf]
//[c]
//[of]:set content (text)
private func set content (m: drop down edit box, text: string)
delete (content (m))
content (m) = new string (text)
end
//[cf]
//[of]:reset selection save
//[c]Resets the selection save
//[c]
private func reset selection save (m: drop down edit box)
def starting position: [1] DWORD
def ending position: [1] DWORD
send message (
m,
CB_GETEDITSEL,
starting position : WPARAM,
ending position : LPARAM)
starting position (m) = starting position []
ending position (m) = ending position []
end
//[cf]
//[of]:check selection changed
//[c]Checks if the selection has changed.
//[c]Compare the current selection to the last saved.
//[c]
private func check selection changed (m: drop down edit box)
def starting position: [1] DWORD
def ending position: [1] DWORD
send message (
m,
CB_GETEDITSEL,
starting position: WPARAM,
ending position: LPARAM)
def changed =
starting position [] <> starting position (m) ||
ending position [] <> ending position (m)
// reset before sending event
starting position (m) = starting position []
ending position (m) = ending position []
if changed
on selection changed (m)
end
end
//[cf]
//[of]:get style
private func get style (m: drop down edit box)
def style = base style (m) | CBS_AUTOHSCROLL | CBS_DROPDOWN | WS_VSCROLL
//if is read only (m)
// style |= ES_READONLY
//end
if edit border (style (m)) == border single
style |= WS_BORDER
end
return style
end
//[cf]
//[of]:get ex style
private func get ex style (m: drop down edit box)
if edit border (style (m)) == border sunken
return WS_EX_CLIENTEDGE
else
return 0:d
end
end
//[cf]
//[c]
//[of]:is dropped down
func is dropped down (m: drop down edit box)
return send message (m, CB_GETDROPPEDSTATE) == 1
end
//[cf]
//[of]:show drop down (show)
//[c]Show / Hide the drop down list
//[c]
func show drop down (m: drop down edit box, show: bool)
send message (m, CB_SHOWDROPDOWN, show:WPARAM)
end
//[cf]
//[cf]
//[cf]
//[of]:drop down edit box class
//[of]:type
public struct drop down edit box class : local box class
// empty
end
//[cf]
//[of]:drop down edit box class
public func drop down edit box class
def c = the drop down edit box class
if ~ initialized
initialized = true
c . copy (box class)
c . release = ^actual release (drop down edit box)
c . compute min size = ^actual compute min size (drop down edit box)
c . on focus = ^handle focus (drop down edit box, event)
c . cut = ^actual cut (drop down edit box)
c . copy = ^actual copy (drop down edit box)
c . paste = ^actual paste (drop down edit box)
c . clear = ^actual clear (drop down edit box)
c . select all = ^actual select all (drop down edit box)
c . can copy = ^actual can copy (drop down edit box)
c . can paste = ^actual can paste (drop down edit box)
c . can clear = ^actual can clear (drop down edit box)
c . can select all = ^yes (box)
c . set read only = ^actual set read only (drop down edit box, bool)
c . accept focus = ^yes (box)
c . wm key down = ^wm key down (drop down edit box, UINT, WPARAM, LPARAM)
c . wm char = ^wm char (drop down edit box, UINT, WPARAM, LPARAM)
c . wm size = ^wm size (drop down edit box, UINT, WPARAM, LPARAM)
c . command = ^actual win command (drop down edit box, WORD)
c . move = ^actual move (drop down edit box, rectangle, bool)
end
return c
end
def initialized = false
def the drop down edit box class: local drop down edit box class
//[cf]
//[cf]
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?