Skip to content

Commit 186a063

Browse files
committed
0.8.0.56: Tab key navigation in file picker for quick control/field switching by keyboard. Minor README fix.
1 parent e825cd7 commit 186a063

3 files changed

Lines changed: 92 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ To install the full SQLite/CE distribution:
6969
- Place the binaries `SQLiteCEdit.exe` and `SQLiteCETest.exe` in a location of your choosing, such as a directory in `\Program Files` or on your storage card.
7070
- Create shortcuts on the desktop and Start menu (`\Windows\Programs`) as desired
7171

72-
# Notes and limitations
72+
# Limitations
7373

7474
SQLite/CE is based on SQLite 2.8, which is quite old (from 2004,) but also much simpler and lighter on memory than newer 3.x releases, while still being much more powerful than the majority of extant database management systems available for Windows CE. But while SQLite/CE can still be very useful, it's important to keep its limitations in mind.
7575

@@ -160,7 +160,7 @@ the public domain.
160160

161161
## Generative AI
162162

163-
The SQLite/CE port and front-end applications have been developed with a lot of
163+
The SQLite/CE port and front-end applications have been developed with significant
164164
AI assistance, primarily from Claude Opus 4.5. While each new feature and change
165165
is fairly well-tested after implementation and during daily use, be aware that
166166
this codebase may have some strange patterns or bugs littered throughout it. The

src/sqlite-ce-edit/filepicker.c

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ static HWND g_hwndPicker = NULL;
1313
static HWND g_hwndList = NULL;
1414
static HWND g_hwndPath = NULL;
1515
static HWND g_hwndFilename = NULL;
16+
static HWND g_hwndOK = NULL;
17+
static HWND g_hwndCancel = NULL;
1618
static wchar_t g_pickerDir[MAX_PATH];
1719
static wchar_t g_pickerResult[MAX_PATH];
1820
static const wchar_t *g_pickerFilter = NULL;
@@ -21,6 +23,7 @@ static int g_pickerSaveMode = 0;
2123
static int g_pickerOK = 0;
2224
static int g_pickerDone = 0;
2325
static WNDPROC g_pfnListProc = NULL;
26+
static WNDPROC g_pfnEditProc = NULL;
2427

2528
/*============================================================================
2629
** Helper: Extract extension filter (e.g., "*.db" from filter string)
@@ -263,12 +266,89 @@ static void OnTypeAhead(wchar_t ch) {
263266
}
264267
}
265268

269+
/*============================================================================
270+
** Tab navigation helper
271+
**============================================================================*/
272+
273+
static void TabNext(HWND from) {
274+
if (from == g_hwndList) SetFocus(g_hwndFilename);
275+
else if (from == g_hwndFilename) SetFocus(g_hwndOK);
276+
else if (from == g_hwndOK) SetFocus(g_hwndCancel);
277+
else SetFocus(g_hwndList);
278+
}
279+
280+
static void TabPrev(HWND from) {
281+
if (from == g_hwndList) SetFocus(g_hwndCancel);
282+
else if (from == g_hwndFilename) SetFocus(g_hwndList);
283+
else if (from == g_hwndOK) SetFocus(g_hwndFilename);
284+
else SetFocus(g_hwndOK);
285+
}
286+
287+
/*============================================================================
288+
** Edit subclass for Tab/Enter handling
289+
**============================================================================*/
290+
291+
static LRESULT CALLBACK PickerEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
292+
if (msg == WM_KEYDOWN) {
293+
if (wParam == VK_TAB) {
294+
if (GetKeyState(VK_SHIFT) & 0x8000)
295+
TabPrev(hwnd);
296+
else
297+
TabNext(hwnd);
298+
return 0;
299+
}
300+
if (wParam == VK_RETURN) {
301+
SendMessageW(g_hwndPicker, WM_COMMAND, IDOK, 0);
302+
return 0;
303+
}
304+
if (wParam == VK_ESCAPE) {
305+
g_pickerOK = 0;
306+
PostMessage(g_hwndPicker, WM_CLOSE, 0, 0);
307+
return 0;
308+
}
309+
}
310+
if (msg == WM_CHAR && wParam == '\t')
311+
return 0;
312+
return CallWindowProc(g_pfnEditProc, hwnd, msg, wParam, lParam);
313+
}
314+
315+
/*============================================================================
316+
** Button subclass for Tab handling
317+
**============================================================================*/
318+
319+
static WNDPROC g_pfnBtnProc = NULL;
320+
321+
static LRESULT CALLBACK PickerBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
322+
if (msg == WM_KEYDOWN) {
323+
if (wParam == VK_TAB) {
324+
if (GetKeyState(VK_SHIFT) & 0x8000)
325+
TabPrev(hwnd);
326+
else
327+
TabNext(hwnd);
328+
return 0;
329+
}
330+
if (wParam == VK_ESCAPE) {
331+
g_pickerOK = 0;
332+
PostMessage(g_hwndPicker, WM_CLOSE, 0, 0);
333+
return 0;
334+
}
335+
}
336+
return CallWindowProc(g_pfnBtnProc, hwnd, msg, wParam, lParam);
337+
}
338+
266339
/*============================================================================
267340
** List subclass for keyboard handling
268341
**============================================================================*/
269342

270343
static LRESULT CALLBACK PickerListProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
271344
if (msg == WM_KEYDOWN) {
345+
if (wParam == VK_TAB) {
346+
if (GetKeyState(VK_SHIFT) & 0x8000)
347+
TabPrev(hwnd);
348+
else
349+
TabNext(hwnd);
350+
return 0;
351+
}
272352
if (wParam == VK_RETURN) {
273353
OnItemActivate();
274354
return 0;
@@ -482,14 +562,21 @@ int CustomFilePicker(HWND hwndOwner, wchar_t *filePath, int maxPath,
482562
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
483563
10, 110, dlgW - 20, 22, g_hwndPicker, (HMENU)102, g_hInst, NULL);
484564

565+
/* Subclass edit */
566+
g_pfnEditProc = (WNDPROC)SetWindowLong(g_hwndFilename, GWL_WNDPROC, (LONG)PickerEditProc);
567+
485568
/* Buttons */
486-
CreateWindowW(L"BUTTON", saveMode ? L"Save" : L"Open",
569+
g_hwndOK = CreateWindowW(L"BUTTON", saveMode ? L"Save" : L"Open",
487570
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
488571
dlgW - 160, 140, 70, 22, g_hwndPicker, (HMENU)IDOK, g_hInst, NULL);
489-
CreateWindowW(L"BUTTON", L"Cancel",
572+
g_hwndCancel = CreateWindowW(L"BUTTON", L"Cancel",
490573
WS_CHILD | WS_VISIBLE,
491574
dlgW - 80, 140, 70, 22, g_hwndPicker, (HMENU)IDCANCEL, g_hInst, NULL);
492575

576+
/* Subclass buttons */
577+
g_pfnBtnProc = (WNDPROC)SetWindowLong(g_hwndOK, GWL_WNDPROC, (LONG)PickerBtnProc);
578+
SetWindowLong(g_hwndCancel, GWL_WNDPROC, (LONG)PickerBtnProc);
579+
493580
/* Populate list */
494581
PopulateFileList();
495582

src/sqlite-ce-edit/globals.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ BOOL WINAPI GetSaveFileNameW(CE_OPENFILENAME*);
8282
** Version
8383
**============================================================================*/
8484

85-
#define SQLITECEDIT_VERSION L"0.8.0.51"
85+
#define SQLITECEDIT_VERSION L"0.8.0.56"
8686

8787
/*============================================================================
8888
** Menu IDs

0 commit comments

Comments
 (0)