⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fl_win32.cxx

📁 PIXIL is a small footprint operating environment, complete with PDA PIM applications, a browser and
💻 CXX
📖 第 1 页 / 共 2 页
字号:
//// "$Id: Fl_win32.cxx,v 1.1.1.1 2003/08/07 21:18:40 jasonk Exp $"//// WIN32-specific code for the Fast Light Tool Kit (FLTK).//// Copyright 1998-1999 by Bill Spitzak and others.//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA.//// Please report all bugs and problems to "fltk-bugs@easysw.com".//// This file contains win32-specific code for fltk which is always linked// in.  Search other files for "WIN32" or filenames ending in _win32.C// for other system-specific code.#include <config.h>#include <FL/Fl.H>#include <FL/win32.H>#include <FL/Fl_Window.H>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <time.h>#include <winsock.h>#include <ctype.h>//// WM_SYNCPAINT is an "undocumented" message, which is finally defined in// VC++ 6.0.//#ifndef WM_SYNCPAINT#  define WM_SYNCPAINT 0x0088#endif /* !WM_SYNCPAINT */#ifndef WM_MOUSELEAVE#  define WM_MOUSELEAVE 0x02a3#endif////////////////////////////////////////////////////////////////// interface to poll/select call:// fd's are only implemented for sockets.  Microsoft Windows does not// have a unified IO system, so it doesn't support select() on files,// devices, or pipes...  Also, unlike UNIX the Windows select() call// doesn't use the nfds parameter, so we don't need to keep track of// the maximum FD number...static fd_set fdsets[3];#define POLLIN 1#define POLLOUT 4#define POLLERR 8static int nfds = 0;static int fd_array_size = 0;static struct FD {  int fd;  short events;  void (*cb)(int, void*);  void* arg;} *fd = 0;void Fl::add_fd(int n, int events, void (*cb)(int, void*), void *v) {  remove_fd(n,events);  int i = nfds++;  if (i >= fd_array_size) {    fd_array_size = 2*fd_array_size+1;    fd = (FD*)realloc(fd, fd_array_size*sizeof(FD));  }  fd[i].fd = n;  fd[i].events = events;  fd[i].cb = cb;  fd[i].arg = v;  if (events & POLLIN) FD_SET(n, &fdsets[0]);  if (events & POLLOUT) FD_SET(n, &fdsets[1]);  if (events & POLLERR) FD_SET(n, &fdsets[2]);}void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) {  Fl::add_fd(fd, POLLIN, cb, v);}void Fl::remove_fd(int n, int events) {  int i,j;  for (i=j=0; i<nfds; i++) {    if (fd[i].fd == n) {      int e = fd[i].events & ~events;      if (!e) continue; // if no events left, delete this fd      fd[i].events = e;    }    // move it down in the array if necessary:    if (j<i) {      fd[j]=fd[i];    }    j++;  }  nfds = j;  if (events & POLLIN) FD_CLR(unsigned(n), &fdsets[0]);  if (events & POLLOUT) FD_CLR(unsigned(n), &fdsets[1]);  if (events & POLLERR) FD_CLR(unsigned(n), &fdsets[2]);}void Fl::remove_fd(int n) {  remove_fd(n, -1);}MSG fl_msg;int fl_ready() {  if (PeekMessage(&fl_msg, NULL, 0, 0, PM_NOREMOVE)) return 1;  timeval t;  t.tv_sec = 0;  t.tv_usec = 0;  fd_set fdt[3];  fdt[0] = fdsets[0];  fdt[1] = fdsets[1];  fdt[2] = fdsets[2];  return ::select(0,&fdt[0],&fdt[1],&fdt[2],&t);}double fl_wait(int timeout_flag, double time) {  int have_message = 0;  int timerid;  if (nfds) {    // For WIN32 we need to poll for socket input FIRST, since    // the event queue is not something we can select() on...    timeval t;    t.tv_sec = 0;    t.tv_usec = 0;    fd_set fdt[3];    fdt[0] = fdsets[0];    fdt[1] = fdsets[1];    fdt[2] = fdsets[2];    if (::select(0,&fdt[0],&fdt[1],&fdt[2],&t)) {      // We got something - do the callback!      for (int i = 0; i < nfds; i ++) {	int f = fd[i].fd;	short revents = 0;	if (FD_ISSET(f,&fdt[0])) revents |= POLLIN;	if (FD_ISSET(f,&fdt[1])) revents |= POLLOUT;	if (FD_ISSET(f,&fdt[2])) revents |= POLLERR;	if (fd[i].events & revents) fd[i].cb(f, fd[i].arg);      }    }  }  // get the first message by waiting the correct amount of time:  if (!timeout_flag) {    // If we are monitoring sockets we need to check them periodically,    // so set a timer in this case...    if (nfds) {      // First see if there is a message waiting...      have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);      if (!have_message) {	// If not then set a 1ms timer...	timerid = SetTimer(NULL, 0, 1, NULL);	GetMessage(&fl_msg, NULL, 0, 0);	KillTimer(NULL, timerid);      }    } else {      // Wait for a message...      GetMessage(&fl_msg, NULL, 0, 0);    }    have_message = 1;  } else {    // Perform the requested timeout...    have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);    if (!have_message && time > 0.0) {      int t = (int)(time * 1000.0);      if (t <= 0) t = 1;      timerid = SetTimer(NULL, 0, t, NULL);      GetMessage(&fl_msg, NULL, 0, 0);      KillTimer(NULL, timerid);      have_message = 1;    }  }  // execute it, them execute any other messages that become ready during it:  while (have_message) {    TranslateMessage(&fl_msg);    DispatchMessage(&fl_msg);    have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE);  }  return time;}////////////////////////////////////////////////////////////////int Fl::x(){  RECT r;  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);  return r.left;}int Fl::y(){  RECT r;  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);  return r.top;}int Fl::h(){  RECT r;  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);  return r.bottom - r.top;}int Fl::w(){  RECT r;  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);  return r.right - r.left;}void Fl::get_mouse(int &x, int &y) {  POINT p;  GetCursorPos(&p);  x = p.x;  y = p.y;}////////////////////////////////////////////////////////////////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.C// 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_COLORMAPextern HPALETTE fl_select_palette(void); // in fl_color_win32.C#endifstatic Fl_Window* resize_bug_fix;static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){  static char buffer[2];  static int cnt=0;  if(uMsg == WM_SYNCPAINT) {    if(cnt) {      InvalidateRect(fl_window,0,FALSE);      cnt = 0;    } else cnt = 1;  } else if (uMsg == WM_PAINT) cnt = 0;  fl_msg.message = uMsg;  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_PAINT: {    // This might be a better alternative, where we fully ignore NT's    // "facilities" for painting. MS expects applications to paint according    // to a very restrictive paradigm, and this is the way I found of    // working around it. In a sense, we are using WM_PAINT simply as an    // "exposure alert", like the X event.    Fl_X *i = Fl_X::i(window);    i->wait_for_expose = 0;    // if region == entire window we should delete i->region, else    if (window->damage()) {      if (i->region) {	InvalidateRgn(hWnd,i->region,FALSE);	GetUpdateRgn(hWnd,i->region,0);      }    } else {      if (!i->region) i->region = CreateRectRgn(0,0,0,0);      GetUpdateRgn(hWnd,i->region,0);    }    window->clear_damage(window->damage()|FL_DAMAGE_EXPOSE);    i->flush();    window->clear_damage();    // This convinces MSWindows we have painted whatever they wanted    // us to paint, and stops it from sending WM_PAINT messages.    ValidateRgn(hWnd,NULL);    } break;  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:    mouse_event(window, 3, 0, wParam, lParam); return 0;#ifdef WM_MOUSELEAVE  case WM_MOUSELEAVE:    Fl::handle(FL_LEAVE, window);    break;#endif /* WM_MOUSELEAVE */  case WM_SETFOCUS:    Fl::handle(FL_FOCUS, window);    break;  case WM_KILLFOCUS:    Fl::handle(FL_UNFOCUS, window);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -