📄 fl_win32.cxx
字号:
Fl::e_length = fl_selection_length[clipboard];
receiver.handle(FL_PASTE);
} else {
if (!OpenClipboard(NULL)) return;
HANDLE h = GetClipboardData(CF_TEXT);
if (h) {
Fl::e_text = (LPSTR)GlobalLock(h);
LPSTR a,b;
a = b = Fl::e_text;
while (*a) { // strip the CRLF pairs ($%$#@^)
if (*a == '\r' && a[1] == '\n') a++;
else *b++ = *a++;
}
*b = 0;
Fl::e_length = b - Fl::e_text;
receiver.handle(FL_PASTE);
GlobalUnlock(h);
}
CloseClipboard();
}
}
////////////////////////////////////////////////////////////////
HWND fl_capture;
static int mouse_event(Fl_Window *window, int what, int button,
WPARAM wParam, LPARAM lParam)
{
static int px, py, pmx, pmy;
POINT pt;
Fl::e_x = pt.x = (signed short)LOWORD(lParam);
Fl::e_y = pt.y = (signed short)HIWORD(lParam);
ClientToScreen(fl_xid(window), &pt);
Fl::e_x_root = pt.x;
Fl::e_y_root = pt.y;
while (window->parent()) {
Fl::e_x += window->x();
Fl::e_y += window->y();
window = window->window();
}
ulong state = Fl::e_state & 0xff0000; // keep shift key states
#if 0
// mouse event reports some shift flags, perhaps save them?
if (wParam & MK_SHIFT) state |= FL_SHIFT;
if (wParam & MK_CONTROL) state |= FL_CTRL;
#endif
if (wParam & MK_LBUTTON) state |= FL_BUTTON1;
if (wParam & MK_MBUTTON) state |= FL_BUTTON2;
if (wParam & MK_RBUTTON) state |= FL_BUTTON3;
Fl::e_state = state;
switch (what) {
case 1: // double-click
if (Fl::e_is_click) {Fl::e_clicks++; goto J1;}
case 0: // single-click
Fl::e_clicks = 0;
J1:
if (!fl_capture) SetCapture(fl_xid(window));
Fl::e_keysym = FL_Button + button;
Fl::e_is_click = 1;
px = pmx = Fl::e_x_root; py = pmy = Fl::e_y_root;
return Fl::handle(FL_PUSH,window);
case 2: // release:
if (!fl_capture) ReleaseCapture();
Fl::e_keysym = FL_Button + button;
return Fl::handle(FL_RELEASE,window);
case 3: // move:
default: // avoid compiler warning
// MSWindows produces extra events even if mouse does not move, ignore em:
if (Fl::e_x_root == pmx && Fl::e_y_root == pmy) return 1;
pmx = Fl::e_x_root; pmy = Fl::e_y_root;
if (abs(Fl::e_x_root-px)>5 || abs(Fl::e_y_root-py)>5) Fl::e_is_click = 0;
return Fl::handle(FL_MOVE,window);
}
}
// convert a MSWindows VK_x to an Fltk (X) Keysym:
// See also the inverse converter in Fl_get_key_win32.cxx
// This table is in numeric order by VK:
static const struct {unsigned short vk, fltk, extended;} vktab[] = {
{VK_BACK, FL_BackSpace},
{VK_TAB, FL_Tab},
{VK_CLEAR, FL_KP+'5', 0xff0b/*XK_Clear*/},
{VK_RETURN, FL_Enter, FL_KP_Enter},
{VK_SHIFT, FL_Shift_L, FL_Shift_R},
{VK_CONTROL, FL_Control_L, FL_Control_R},
{VK_MENU, FL_Alt_L, FL_Alt_R},
{VK_PAUSE, FL_Pause},
{VK_CAPITAL, FL_Caps_Lock},
{VK_ESCAPE, FL_Escape},
{VK_SPACE, ' '},
{VK_PRIOR, FL_KP+'9', FL_Page_Up},
{VK_NEXT, FL_KP+'3', FL_Page_Down},
{VK_END, FL_KP+'1', FL_End},
{VK_HOME, FL_KP+'7', FL_Home},
{VK_LEFT, FL_KP+'4', FL_Left},
{VK_UP, FL_KP+'8', FL_Up},
{VK_RIGHT, FL_KP+'6', FL_Right},
{VK_DOWN, FL_KP+'2', FL_Down},
{VK_SNAPSHOT, FL_Print}, // does not work on NT
{VK_INSERT, FL_KP+'0', FL_Insert},
{VK_DELETE, FL_KP+'.', FL_Delete},
{VK_LWIN, FL_Meta_L},
{VK_RWIN, FL_Meta_R},
{VK_APPS, FL_Menu},
{VK_MULTIPLY, FL_KP+'*'},
{VK_ADD, FL_KP+'+'},
{VK_SUBTRACT, FL_KP+'-'},
{VK_DECIMAL, FL_KP+'.'},
{VK_DIVIDE, FL_KP+'/'},
{VK_NUMLOCK, FL_Num_Lock},
{VK_SCROLL, FL_Scroll_Lock},
{0xba, ';'},
{0xbb, '='},
{0xbc, ','},
{0xbd, '-'},
{0xbe, '.'},
{0xbf, '/'},
{0xc0, '`'},
{0xdb, '['},
{0xdc, '\\'},
{0xdd, ']'},
{0xde, '\''}
};
static int ms2fltk(int vk, int extended) {
static unsigned short vklut[256];
static unsigned short extendedlut[256];
if (!vklut[1]) { // init the table
unsigned int i;
for (i = 0; i < 256; i++) vklut[i] = tolower(i);
for (i=VK_F1; i<=VK_F16; i++) vklut[i] = i+(FL_F-(VK_F1-1));
for (i=VK_NUMPAD0; i<=VK_NUMPAD9; i++) vklut[i] = i+(FL_KP+'0'-VK_NUMPAD0);
for (i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) {
vklut[vktab[i].vk] = vktab[i].fltk;
extendedlut[vktab[i].vk] = vktab[i].extended;
}
for (i = 0; i < 256; i++) if (!extendedlut[i]) extendedlut[i] = vklut[i];
}
return extended ? extendedlut[vk] : vklut[vk];
}
#if USE_COLORMAP
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
#endif
static Fl_Window* resize_bug_fix;
extern void fl_save_pen(void);
extern void fl_restore_pen(void);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Copy the message to fl_msg so add_handler code can see it, it is
// already there if this is called by DispatchMessage, but not if
// Windows calls this directly.
fl_msg.hwnd = hWnd;
fl_msg.message = uMsg;
fl_msg.wParam = wParam;
fl_msg.lParam = lParam;
//fl_msg.time = ???
//fl_msg.pt = ???
//fl_msg.lPrivate = ???
Fl_Window *window = fl_find(hWnd);
if (window) switch (uMsg) {
case WM_QUIT: // this should not happen?
Fl::fatal("WM_QUIT message");
case WM_CLOSE: // user clicked close box
Fl::handle(FL_CLOSE, window);
return 0;
case WM_SYNCPAINT :
case WM_NCPAINT :
case WM_ERASEBKGND :
// Andreas Weitl - WM_SYNCPAINT needs to be passed to DefWindowProc
// so that Windows can generate the proper paint messages...
// Similarly, WM_NCPAINT and WM_ERASEBKGND need this, too...
break;
case WM_PAINT: {
Fl_Region R;
Fl_X *i = Fl_X::i(window);
i->wait_for_expose = 0;
if (!i->region && window->damage()) {
// Redraw the whole window...
i->region = CreateRectRgn(0, 0, window->w(), window->h());
} else {
// We need to merge WIN32's damage into FLTK's damage.
R = CreateRectRgn(0,0,0,0);
GetUpdateRgn(hWnd,R,0);
if (i->region) {
// Also tell WIN32 that we are drawing someplace else as well...
InvalidateRgn(hWnd, i->region, FALSE);
CombineRgn(i->region, i->region, R, RGN_OR);
XDestroyRegion(R);
} else {
i->region = R;
}
}
window->clear_damage((uchar)(window->damage()|FL_DAMAGE_EXPOSE));
// These next two statements should not be here, so that all update
// is deferred until Fl::flush() is called during idle. However WIN32
// apparently is very unhappy if we don't obey it and draw right now.
// Very annoying!
fl_GetDC(hWnd); // Make sure we have a DC for this window...
fl_save_pen();
i->flush();
fl_restore_pen();
ValidateRgn(hWnd,i->region);
window->clear_damage();
} return 0;
case WM_LBUTTONDOWN: mouse_event(window, 0, 1, wParam, lParam); return 0;
case WM_LBUTTONDBLCLK:mouse_event(window, 1, 1, wParam, lParam); return 0;
case WM_LBUTTONUP: mouse_event(window, 2, 1, wParam, lParam); return 0;
case WM_MBUTTONDOWN: mouse_event(window, 0, 2, wParam, lParam); return 0;
case WM_MBUTTONDBLCLK:mouse_event(window, 1, 2, wParam, lParam); return 0;
case WM_MBUTTONUP: mouse_event(window, 2, 2, wParam, lParam); return 0;
case WM_RBUTTONDOWN: mouse_event(window, 0, 3, wParam, lParam); return 0;
case WM_RBUTTONDBLCLK:mouse_event(window, 1, 3, wParam, lParam); return 0;
case WM_RBUTTONUP: mouse_event(window, 2, 3, wParam, lParam); return 0;
case WM_MOUSEMOVE:
#ifdef USE_TRACK_MOUSE
if (Fl::belowmouse() != window) {
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
_TrackMouseEvent(&tme);
}
#endif // USE_TRACK_MOUSE
mouse_event(window, 3, 0, wParam, lParam);
return 0;
case WM_MOUSELEAVE:
Fl::belowmouse(0);
if (!window->parent()) Fl::handle(FL_LEAVE, window);
break;
case WM_SETFOCUS:
Fl::handle(FL_FOCUS, window);
break;
case WM_KILLFOCUS:
Fl::handle(FL_UNFOCUS, window);
Fl::flush(); // it never returns to main loop when deactivated...
break;
case WM_SHOWWINDOW:
if (!window->parent()) {
Fl::handle(wParam ? FL_SHOW : FL_HIDE, window);
}
break;
case WM_ACTIVATEAPP:
// From eric@vfx.sel.sony.com, we should process WM_ACTIVATEAPP
// messages to restore the correct state of the shift/ctrl/alt/lock
// keys... Added control, shift, alt, and meta keys, and changed
// to use GetAsyncKeyState and do it when wParam is 1
// (that means we have focus...)
if (wParam)
{
ulong state = 0;
if (GetAsyncKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK;
if (GetAsyncKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK;
if (GetAsyncKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
if (GetAsyncKeyState(VK_CONTROL)&~1) state |= FL_CTRL;
if (GetAsyncKeyState(VK_SHIFT)&~1) state |= FL_SHIFT;
if (GetAsyncKeyState(VK_MENU)) state |= FL_ALT;
if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1) state |= FL_META;
Fl::e_state = state;
return 0;
}
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
// save the keysym until we figure out the characters:
Fl::e_keysym = ms2fltk(wParam,lParam&(1<<24));
// See if TranslateMessage turned it into a WM_*CHAR message:
if (PeekMessage(&fl_msg, hWnd, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
uMsg = fl_msg.message;
wParam = fl_msg.wParam;
lParam = fl_msg.lParam;
}
case WM_DEADCHAR:
case WM_SYSDEADCHAR:
case WM_CHAR:
case WM_SYSCHAR: {
ulong state = Fl::e_state & 0xff000000; // keep the mouse button state
// if GetKeyState is expensive we might want to comment some of these out:
if (GetKeyState(VK_SHIFT)&~1) state |= FL_SHIFT;
if (GetKeyState(VK_CAPITAL)) state |= FL_CAPS_LOCK;
if (GetKeyState(VK_CONTROL)&~1) state |= FL_CTRL;
// Alt gets reported for the Alt-GR switch on foreign keyboards.
// so we need to check the event as well to get it right:
if ((lParam&(1<<29)) //same as GetKeyState(VK_MENU)
&& uMsg != WM_CHAR) state |= FL_ALT;
if (GetKeyState(VK_NUMLOCK)) state |= FL_NUM_LOCK;
if ((GetKeyState(VK_LWIN)|GetKeyState(VK_RWIN))&~1) {
// WIN32 bug? GetKeyState returns garbage if the user hit the
// meta key to pop up start menu. Sigh.
if ((GetAsyncKeyState(VK_LWIN)|GetAsyncKeyState(VK_RWIN))&~1)
state |= FL_META;
}
if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
Fl::e_state = state;
if (lParam & (1<<31)) { // key up events.
if (Fl::handle(FL_KEYUP, window)) return 0;
break;
}
static char buffer[2];
if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
buffer[0] = char(wParam);
Fl::e_length = 1;
} else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
buffer[0] = Fl::e_keysym-FL_KP;
Fl::e_length = 1;
} else {
buffer[0] = 0;
Fl::e_length = 0;
}
Fl::e_text = buffer;
// for (int i = lParam&0xff; i--;)
while (window->parent()) window = window->window();
if (Fl::handle(FL_KEYBOARD,window)) return 0;
break;}
case WM_MOUSEWHEEL: {
static int delta = 0; // running total of all motion
delta += (SHORT)(HIWORD(wParam));
Fl::e_dy = -delta / WHEEL_DELTA;
delta += Fl::e_dy * WHEEL_DELTA;
if (Fl::e_dy) Fl::handle(FL_MOUSEWHEEL, window);
return 0;
}
case WM_GETMINMAXINFO:
Fl_X::i(window)->set_minmax((LPMINMAXINFO)lParam);
break;
case WM_SIZE:
if (!window->parent()) {
if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) {
Fl::handle(FL_HIDE, window);
} else {
Fl::handle(FL_SHOW, window);
resize_bug_fix = window;
window->size(LOWORD(lParam), HIWORD(lParam));
}
}
break;
case WM_MOVE:
resize_bug_fix = window;
window->position(LOWORD(lParam), HIWORD(lParam));
break;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT) {
while (window->parent()) window = window->window();
SetCursor(Fl_X::i(window)->cursor);
return 0;
}
break;
#if USE_COLORMAP
case WM_QUERYNEWPALETTE :
fl_GetDC(hWnd);
if (fl_select_palette()) InvalidateRect(hWnd, NULL, FALSE);
break;
case WM_PALETTECHANGED:
fl_GetDC(hWnd);
if ((HWND)wParam != hWnd && fl_select_palette()) UpdateColors(fl_gc);
break;
case WM_CREATE :
fl_GetDC(hWnd);
fl_select_palette();
break;
#endif
case WM_DESTROYCLIPBOARD:
fl_i_own_selection[1] = 0;
return 1;
case WM_RENDERALLFORMATS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -