Added OpenFile(), the first dialog to be added, and implemented it on Windows... mostly.
This commit is contained in:
parent
b6bf7402ab
commit
cb4d28cc1c
|
@ -0,0 +1,10 @@
|
||||||
|
// 18 august 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
// OpenFile opens a dialog box that asks the user to choose a file.
|
||||||
|
// It returns the selected filename, or an empty string if no file was chosen.
|
||||||
|
// All events stop while OpenFile is executing. (TODO move to doc.go)
|
||||||
|
func OpenFile() (filename string) {
|
||||||
|
return openFile()
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
// 18 august 2014
|
||||||
|
|
||||||
|
#include "winapi_windows.h"
|
||||||
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
// this should be reasonable
|
||||||
|
#define NFILENAME 4096
|
||||||
|
|
||||||
|
WCHAR *openFile(void)
|
||||||
|
{
|
||||||
|
OPENFILENAMEW ofn;
|
||||||
|
DWORD err;
|
||||||
|
WCHAR *filenameBuffer;
|
||||||
|
|
||||||
|
// freed on the Go side
|
||||||
|
filenameBuffer = (WCHAR *) malloc((NFILENAME + 1) * sizeof (WCHAR));
|
||||||
|
if (filenameBuffer == NULL)
|
||||||
|
xpanic("memory exhausted in OpenFile()", GetLastError());
|
||||||
|
filenameBuffer[0] = L'\0'; // required by GetOpenFileName() to indicate no previous filename
|
||||||
|
ZeroMemory(&ofn, sizeof (OPENFILENAMEW));
|
||||||
|
ofn.lStructSize = sizeof (OPENFILENAMEW);
|
||||||
|
ofn.hwndOwner = NULL;
|
||||||
|
ofn.hInstance = hInstance;
|
||||||
|
ofn.lpstrFilter = NULL; // no filters
|
||||||
|
ofn.lpstrFile = filenameBuffer;
|
||||||
|
ofn.nMaxFile = NFILENAME + 1; // TODO include + 1?
|
||||||
|
ofn.lpstrInitialDir = NULL; // let system decide
|
||||||
|
ofn.lpstrTitle = NULL; // let system decide
|
||||||
|
// TODO OFN_SHAREAWARE?
|
||||||
|
// TODO remove OFN_NODEREFERENCELINKS? or does no filters ensure that anyway?
|
||||||
|
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_FORCESHOWHIDDEN | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_NOCHANGEDIR | OFN_NODEREFERENCELINKS | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST;
|
||||||
|
if (GetOpenFileNameW(&ofn) == FALSE) {
|
||||||
|
// TODO stringify
|
||||||
|
err = CommDlgExtendedError();
|
||||||
|
if (err == 0) // user cancelled
|
||||||
|
return NULL;
|
||||||
|
xpanic("error running open file dialog", GetLastError());
|
||||||
|
}
|
||||||
|
return filenameBuffer;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 18 august 2014
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// #include "winapi_windows.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// TODO move to common_windows.go
|
||||||
|
func wstrToString(wstr *C.WCHAR) string {
|
||||||
|
n := C.wcslen((*C.wchar_t)(unsafe.Pointer(wstr)))
|
||||||
|
xbuf := &reflect.SliceHeader{
|
||||||
|
Data: uintptr(unsafe.Pointer(wstr)),
|
||||||
|
Len: int(n + 1),
|
||||||
|
Cap: int(n + 1),
|
||||||
|
}
|
||||||
|
buf := (*[]uint16)(unsafe.Pointer(xbuf))
|
||||||
|
return syscall.UTF16ToString(*buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openFile() string {
|
||||||
|
name := C.openFile()
|
||||||
|
if name == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
defer C.free(unsafe.Pointer(name))
|
||||||
|
return wstrToString(name)
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// #cgo CFLAGS: --std=c99
|
// #cgo CFLAGS: --std=c99
|
||||||
// #cgo LDFLAGS: -luser32 -lkernel32 -lgdi32 -luxtheme -lmsimg32
|
// #cgo LDFLAGS: -luser32 -lkernel32 -lgdi32 -luxtheme -lmsimg32 -lcomdlg32
|
||||||
// #include "winapi_windows.h"
|
// #include "winapi_windows.h"
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
|
|
@ -133,4 +133,7 @@ enum {
|
||||||
extern HIMAGELIST checkboxImageList;
|
extern HIMAGELIST checkboxImageList;
|
||||||
extern void makeCheckboxImageList(HWND);
|
extern void makeCheckboxImageList(HWND);
|
||||||
|
|
||||||
|
// dialog_windows.c
|
||||||
|
extern WCHAR *openFile(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -38,6 +38,8 @@ type testwin struct {
|
||||||
festart Button
|
festart Button
|
||||||
felabel Label
|
felabel Label
|
||||||
festop Button
|
festop Button
|
||||||
|
openbtn Button
|
||||||
|
fnlabel Label
|
||||||
icons []icon
|
icons []icon
|
||||||
il ImageList
|
il ImageList
|
||||||
icontbl Table
|
icontbl Table
|
||||||
|
@ -89,7 +91,19 @@ func (tw *testwin) addfe() {
|
||||||
tw.fe = nil
|
tw.fe = nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
tw.festack = NewVerticalStack(tw.festart, tw.felabel, tw.festop)
|
tw.openbtn = NewButton("Open")
|
||||||
|
tw.openbtn.OnClicked(func() {
|
||||||
|
fn := OpenFile()
|
||||||
|
if fn == "" {
|
||||||
|
fn = "<no file selected>"
|
||||||
|
}
|
||||||
|
tw.fnlabel.SetText(fn)
|
||||||
|
})
|
||||||
|
tw.fnlabel = NewStandaloneLabel("<no file selected>")
|
||||||
|
tw.festack = NewVerticalStack(tw.festart, tw.felabel, tw.festop,
|
||||||
|
Space(),
|
||||||
|
tw.openbtn, tw.fnlabel)
|
||||||
|
tw.festack.SetStretchy(3)
|
||||||
tw.t.Append("Foreign Events", tw.festack)
|
tw.t.Append("Foreign Events", tw.festack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue