Exemple #1
0
// an up-down control will only properly position itself the first time
// stupidly, there are no messages to force a size calculation, nor can I seem to reset the buddy window to force a new position
// alas, we have to make a new up/down control each time :(
// TODO we'll need to store a copy of the current position and range for this
func (s *spinbox) remakeUpDown() {
	// destroying the previous one, setting the parent properly, and subclassing are handled here
	s.hwndUpDown = C.newUpDown(s.hwndUpDown, unsafe.Pointer(s))
	// for this to work, hwndUpDown needs to have rect [0 0 0 0]
	C.moveWindow(s.hwndUpDown, 0, 0, 0, 0)
	C.SendMessageW(s.hwndUpDown, C.UDM_SETBUDDY, C.WPARAM(uintptr(unsafe.Pointer(s.hwndEdit))), 0)
	C.SendMessageW(s.hwndUpDown, C.UDM_SETRANGE32, C.WPARAM(s.min), C.LPARAM(s.max))
	C.SendMessageW(s.hwndUpDown, C.UDM_SETPOS32, 0, C.LPARAM(s.value))
	if s.updownVisible {
		C.ShowWindow(s.hwndUpDown, C.SW_SHOW)
	}
}
Exemple #2
0
func finishNewTable(b *tablebase, ty reflect.Type) Table {
	hwnd := C.newControl(C.xtableWindowClass,
		C.WS_HSCROLL|C.WS_VSCROLL|C.WS_TABSTOP,
		C.WS_EX_CLIENTEDGE) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
	t := &table{
		controlSingleHWND: newControlSingleHWND(hwnd),
		tablebase:         b,
		selected:          newEvent(),
		free:              make(map[C.uintptr_t]bool),
	}
	t.fpreferredSize = t.xpreferredSize
	t.chainresize = t.fresize
	t.fresize = t.xresize
	C.setTableSubclass(t.hwnd, unsafe.Pointer(t))
	// TODO listview didn't need this; someone mentioned (TODO) it uses the small caption font???
	C.controlSetControlFont(t.hwnd)
	for i := 0; i < ty.NumField(); i++ {
		coltype := C.WPARAM(C.tableColumnText)
		switch {
		case ty.Field(i).Type == reflect.TypeOf((*image.RGBA)(nil)):
			coltype = C.tableColumnImage
		case ty.Field(i).Type.Kind() == reflect.Bool:
			coltype = C.tableColumnCheckbox
		}
		colname := ty.Field(i).Tag.Get("uicolumn")
		if colname == "" {
			colname = ty.Field(i).Name
		}
		ccolname := toUTF16(colname)
		C.SendMessageW(t.hwnd, C.tableAddColumn, coltype, C.LPARAM(uintptr(unsafe.Pointer(ccolname))))
		// TODO free ccolname
	}
	t.colcount = C.int(ty.NumField())
	return t
}
Exemple #3
0
func (a *area) Repaint(r image.Rectangle) {
	var hscroll, vscroll C.int
	var rect C.RECT

	C.SendMessageW(a.hwnd, C.msgAreaGetScroll, C.WPARAM(uintptr(unsafe.Pointer(&hscroll))), C.LPARAM(uintptr(unsafe.Pointer(&vscroll))))
	r = r.Add(image.Pt(int(hscroll), int(vscroll))) // adjust by scroll position
	r = image.Rect(0, 0, a.width, a.height).Intersect(r)
	if r.Empty() {
		return
	}
	rect.left = C.LONG(r.Min.X)
	rect.top = C.LONG(r.Min.Y)
	rect.right = C.LONG(r.Max.X)
	rect.bottom = C.LONG(r.Max.Y)
	C.SendMessageW(a.hwnd, C.msgAreaRepaint, 0, C.LPARAM(uintptr(unsafe.Pointer(&rect))))
}
Exemple #4
0
func (p *progressbar) SetPercent(percent int) {
	if percent < 0 || percent > 100 {
		panic(fmt.Errorf("given ProgressBar percentage %d out of range", percent))
	}
	// TODO circumvent aero
	C.SendMessageW(p.hwnd, C.PBM_SETPOS, C.WPARAM(percent), 0)
}
Exemple #5
0
func (i *imagelist) apply(hwnd C.HWND, uMsg C.UINT) {
	width := C.GetSystemMetrics(C.SM_CXSMICON)
	height := C.GetSystemMetrics(C.SM_CYSMICON)
	il := C.newImageList(width, height)
	for index := range i.list {
		C.addImage(il, hwnd, i.list[index], C.int(i.width[index]), C.int(i.height[index]), width, height)
	}
	C.SendMessageW(hwnd, uMsg, 0, C.LPARAM(uintptr(unsafe.Pointer(il))))
}
Exemple #6
0
func (b *button) preferredSize(d *sizing) (width, height int) {
	// comctl32.dll version 6 thankfully provides a method to grab this...
	var size C.SIZE

	size.cx = 0 // explicitly ask for ideal size
	size.cy = 0
	if C.SendMessageW(b._hwnd, C.BCM_GETIDEALSIZE, 0, C.LPARAM(uintptr(unsafe.Pointer(&size)))) != C.FALSE {
		return int(size.cx), int(size.cy)
	}
	// that failed, fall back
	println("message failed; falling back")
	// don't worry about the error return from GetSystemMetrics(); there's no way to tell (explicitly documented as such)
	xmargins := 2 * int(C.GetSystemMetrics(C.SM_CXEDGE))
	return xmargins + int(b._textlen), fromdlgunitsY(buttonHeight, d)
}
Exemple #7
0
//export spinboxEditChanged
func spinboxEditChanged(data unsafe.Pointer) {
	// we're basically on our own here
	s := (*spinbox)(unsafe.Pointer(data))
	// this basically does what OS X does: values too low get clamped to the minimum, values too high get clamped to the maximum, and deleting everything clamps to the minimum
	value, err := strconv.Atoi(getWindowText(s.hwndEdit))
	if err != nil {
		// best we can do fo rnow in this case :S
		// a partial atoi() like in C would be more optimal
		// it handles the deleting everything case just fine
		value = s.min
	}
	s.value = value
	s.cap()
	C.SendMessageW(s.hwndUpDown, C.UDM_SETPOS32, 0, C.LPARAM(s.value))
	// TODO position the insertion caret at the end (or wherever is appropriate)
	s.changed.fire()
}
Exemple #8
0
// a tab control contains other controls; size appropriately
func (t *tab) commitResize(c *allocation, d *sizing) {
	var r C.RECT

	// figure out what the rect for each child is...
	// the tab contents are children of the tab itself, so ignore c.x and c.y, which are relative to the window!
	r.left = C.LONG(0)
	r.top = C.LONG(0)
	r.right = C.LONG(c.width)
	r.bottom = C.LONG(c.height)
	C.tabGetContentRect(t._hwnd, &r)
	// and resize tabs
	// resize only the current tab; we trigger a resize on a tab change to make sure things look correct
	if len(t.tabs) > 0 {
		t.tabs[C.SendMessageW(t._hwnd, C.TCM_GETCURSEL, 0, 0)].move(&r)
	}
	// save the tab size so we can
	t.switchrect = r
	// and now resize the tab control itself
	basecommitResize(t, c, d)
}
Exemple #9
0
func finishNewTable(b *tablebase, ty reflect.Type) Table {
	t := &table{
		_hwnd: C.newControl(C.xWC_LISTVIEW,
			C.LVS_REPORT|C.LVS_OWNERDATA|C.LVS_NOSORTHEADER|C.LVS_SHOWSELALWAYS|C.LVS_SINGLESEL|C.WS_HSCROLL|C.WS_VSCROLL|C.WS_TABSTOP,
			C.WS_EX_CLIENTEDGE), // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
		tablebase: b,
		hotrow:    -1,
		hotcol:    -1,
		pushedrow: -1,
		pushedcol: -1,
		selected:  newEvent(),
	}
	C.setTableSubclass(t._hwnd, unsafe.Pointer(t))
	// LVS_EX_FULLROWSELECT gives us selection across the whole row, not just the leftmost column; this makes the list view work like on other platforms
	// LVS_EX_SUBITEMIMAGES gives us images in subitems, which will be important when both images and checkboxes are added
	C.tableAddExtendedStyles(t._hwnd, C.LVS_EX_FULLROWSELECT|C.LVS_EX_SUBITEMIMAGES)
	// this must come after the subclass because it uses one of our private messages
	C.SendMessageW(t._hwnd, C.msgTableMakeInitialCheckboxImageList, 0, 0)
	for i := 0; i < ty.NumField(); i++ {
		C.tableAppendColumn(t._hwnd, C.int(i), toUTF16(ty.Field(i).Name))
	}
	t.colcount = C.int(ty.NumField())
	return t
}
Exemple #10
0
func (a *area) RepaintAll() {
	C.SendMessageW(a.hwnd, C.msgAreaRepaintAll, 0, 0)
}
Exemple #11
0
func (a *area) SetSize(width, height int) {
	a.width = width
	a.height = height
	C.SendMessageW(a.hwnd, C.msgAreaSizeChanged, 0, 0)
}
Exemple #12
0
func (p *progressbar) Percent() int {
	return int(C.SendMessageW(p.hwnd, C.PBM_GETPOS, 0, 0))
}
Exemple #13
0
func (s *spinbox) SetValue(value int) {
	// UDM_SETPOS32 is documented to do what we want, but since we're keeping a copy of value we need to do it anyway
	s.value = value
	s.cap()
	C.SendMessageW(s.hwndUpDown, C.UDM_SETPOS32, 0, C.LPARAM(s.value))
}