📄 fl_win32.cxx
字号:
fl_i_own_selection[1] = 0;
// Windoze seems unhappy unless I do these two steps. Documentation
// seems to vary on whether opening the clipboard is necessary or
// is in fact wrong:
CloseClipboard();
OpenClipboard(NULL);
// fall through...
case WM_RENDERFORMAT: {
HANDLE h = GlobalAlloc(GHND, fl_selection_length[1]+1);
if (h) {
LPSTR p = (LPSTR)GlobalLock(h);
memcpy(p, fl_selection_buffer[1], fl_selection_length[1]);
p[fl_selection_length[1]] = 0;
GlobalUnlock(h);
SetClipboardData(CF_TEXT, h);
}
// Windoze also seems unhappy if I don't do this. Documentation very
// unclear on what is correct:
if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard();
return 1;}
default:
if (Fl::handle(0,0)) return 0;
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
////////////////////////////////////////////////////////////////
// This function gets the dimensions of the top/left borders and
// the title bar, if there is one, based on the FL_BORDER, FL_MODAL
// and FL_NONMODAL flags, and on the window's size range.
// It returns the following values:
//
// value | border | title bar
// 0 | none | no
// 1 | fix | yes
// 2 | size | yes
int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
int W, H, xoff, yoff, dx, dy;
int ret = bx = by = bt = 0;
if (w->border() && !w->parent()) {
if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) {
ret = 2;
bx = GetSystemMetrics(SM_CXSIZEFRAME);
by = GetSystemMetrics(SM_CYSIZEFRAME);
} else {
ret = 1;
bx = GetSystemMetrics(SM_CXFIXEDFRAME);
by = GetSystemMetrics(SM_CYFIXEDFRAME);
}
bt = GetSystemMetrics(SM_CYCAPTION);
}
//The coordinates of the whole window, including non-client area
xoff = bx;
yoff = by + bt;
dx = 2*bx;
dy = 2*by + bt;
X = w->x()-xoff;
Y = w->y()-yoff;
W = w->w()+dx;
H = w->h()+dy;
//Proceed to positioning the window fully inside the screen, if possible
//Make border's lower right corner visible
if (Fl::w() < X+W) X = Fl::w() - W;
if (Fl::h() < Y+H) Y = Fl::h() - H;
//Make border's upper left corner visible
if (X<0) X = 0;
if (Y<0) Y = 0;
//Make client area's lower right corner visible
if (Fl::w() < X+dx+ w->w()) X = Fl::w() - w->w() - dx;
if (Fl::h() < Y+dy+ w->h()) Y = Fl::h() - w->h() - dy;
//Make client area's upper left corner visible
if (X+xoff < 0) X = -xoff;
if (Y+yoff < 0) Y = -yoff;
//Return the client area's top left corner in (X,Y)
X+=xoff;
Y+=yoff;
return ret;
}
////////////////////////////////////////////////////////////////
void Fl_Window::resize(int X,int Y,int W,int H) {
UINT flags = SWP_NOSENDCHANGING | SWP_NOZORDER;
int is_a_resize = (W != w() || H != h());
int resize_from_program = (this != resize_bug_fix);
if (!resize_from_program) resize_bug_fix = 0;
if (X != x() || Y != y()) {
set_flag(FL_FORCE_POSITION);
} else {
if (!is_a_resize) return;
flags |= SWP_NOMOVE;
}
if (is_a_resize) {
Fl_Group::resize(X,Y,W,H);
if (shown()) {redraw(); i->wait_for_expose = 1;}
} else {
x(X); y(Y);
flags |= SWP_NOSIZE;
}
if (!border()) flags |= SWP_NOACTIVATE;
if (resize_from_program && shown()) {
if (!resizable()) size_range(w(),h(),w(),h());
int dummy, bt, bx, by;
//Ignore window managing when resizing, so that windows (and more
//specifically menus) can be moved offscreen.
if (Fl_X::fake_X_wm(this, dummy, dummy, bt, bx, by)) {
X -= bx;
Y -= by+bt;
W += 2*bx;
H += 2*by+bt;
}
SetWindowPos(i->xid, 0, X, Y, W, H, flags);
}
}
////////////////////////////////////////////////////////////////
void fl_fix_focus(); // in Fl.cxx
char fl_show_iconic; // hack for Fl_Window::iconic()
// int fl_background_pixel = -1; // color to use for background
HCURSOR fl_default_cursor;
UINT fl_wake_msg = 0;
int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
Fl_X* Fl_X::make(Fl_Window* w) {
Fl_Group::current(0); // get rid of very common user bug: forgot end()
const char* class_name = /*w->xclass();
if (!class_name) class_name =*/ "FLTK"; // create a "FLTK" WNDCLASS
const char* message_name = "FLTK::ThreadWakeup";
WNDCLASSEX wc;
// Documentation states a device context consumes about 800 bytes
// of memory... so who cares? If 800 bytes per window is what it
// takes to speed things up, I'm game.
//wc.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC | CS_DBLCLKS;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = fl_display;
if (!w->icon())
w->icon((void *)LoadIcon(NULL, IDI_APPLICATION));
wc.hIcon = wc.hIconSm = (HICON)w->icon();
wc.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW);
//uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b);
//wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b));
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = class_name;
wc.cbSize = sizeof(WNDCLASSEX);
RegisterClassEx(&wc);
if (!fl_wake_msg) fl_wake_msg = RegisterWindowMessage(message_name);
HWND parent;
DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
DWORD styleEx = WS_EX_LEFT;
int xp = w->x();
int yp = w->y();
int wp = w->w();
int hp = w->h();
int showit = 1;
if (w->parent()) {
style |= WS_CHILD;
styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
parent = fl_xid(w->window());
} else {
if (!w->size_range_set) {
if (w->resizable()) {
Fl_Widget *o = w->resizable();
int minw = o->w(); if (minw > 100) minw = 100;
int minh = o->h(); if (minh > 100) minh = 100;
w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
} else {
w->size_range(w->w(), w->h(), w->w(), w->h());
}
}
styleEx |= WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT;
int xwm = xp , ywm = yp , bt, bx, by;
switch (fake_X_wm(w, xwm, ywm, bt, bx, by)) {
// No border (used for menus)
case 0: style |= WS_POPUP;
styleEx |= WS_EX_TOOLWINDOW;
break;
// Thin border and title bar
case 1: style |= WS_DLGFRAME | WS_CAPTION; break;
// Thick, resizable border and title bar, with maximize button
case 2: style |= WS_THICKFRAME | WS_MAXIMIZEBOX | WS_CAPTION ; break;
}
if (by+bt) {
if (!w->modal()) style |= WS_SYSMENU | WS_MINIMIZEBOX;
wp += 2*bx;
hp += 2*by+bt;
}
if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
xp = yp = CW_USEDEFAULT;
} else {
if (!Fl::grab()) {
xp = xwm; yp = ywm;
w->x(xp);w->y(yp);
}
xp -= bx;
yp -= by+bt;
}
parent = 0;
if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) {
// find some other window to be "transient for":
Fl_Window* w = Fl_X::first->w;
while (w->parent()) w = w->window();
parent = fl_xid(w);
if (!w->visible()) showit = 0;
} else if (Fl::grab()) parent = fl_xid(Fl::grab());
}
Fl_X* x = new Fl_X;
x->other_xid = 0;
x->setwindow(w);
x->region = 0;
x->private_dc = 0;
x->cursor = fl_default_cursor;
x->xid = CreateWindowEx(
styleEx,
class_name, w->label(), style,
xp, yp, wp, hp,
parent,
NULL, // menu
fl_display,
NULL // creation parameters
);
x->next = Fl_X::first;
Fl_X::first = x;
x->wait_for_expose = 1;
if (fl_show_iconic) {showit = 0; fl_show_iconic = 0;}
if (showit) {
w->set_visible();
w->handle(FL_SHOW); // get child windows to appear
w->redraw(); // force draw to happen
}
// If we've captured the mouse, we dont want do activate any
// other windows from the code, or we loose the capture.
ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE :
(Fl::grab() || (style & WS_POPUP)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL);
// Drag-n-drop requires GCC 3.x or a non-GNU compiler...
#if !defined(__GNUC__) || __GNUC__ >= 3
// Register all windows for potential drag'n'drop operations
static char oleInitialized = 0;
if (!oleInitialized) { OleInitialize(0L); oleInitialized=1; }
RegisterDragDrop(x->xid, flIDropTarget);
#endif // !__GNUC__ || __GNUC__ >= 3
if (w->modal()) {Fl::modal_ = w; fl_fix_focus();}
return x;
}
////////////////////////////////////////////////////////////////
HINSTANCE fl_display = GetModuleHandle(NULL);
void Fl_Window::size_range_() {
size_range_set = 1;
}
void Fl_X::set_minmax(LPMINMAXINFO minmax)
{
int td, wd, hd, dummy;
fake_X_wm(w, dummy, dummy, td, wd, hd);
wd *= 2;
hd *= 2;
hd += td;
minmax->ptMinTrackSize.x = w->minw + wd;
minmax->ptMinTrackSize.y = w->minh + hd;
if (w->maxw) {
minmax->ptMaxTrackSize.x = w->maxw + wd;
minmax->ptMaxSize.x = w->maxw + wd;
}
if (w->maxh) {
minmax->ptMaxTrackSize.y = w->maxh + hd;
minmax->ptMaxSize.y = w->maxh + hd;
}
}
////////////////////////////////////////////////////////////////
#include <FL/filename.H> // need so FL_EXPORT fl_filename_name works
// returns pointer to the filename, or null if name ends with '/'
const char *fl_filename_name(const char *name) {
const char *p,*q;
if (!name) return (0);
q = name;
if (q[0] && q[1]==':') q += 2; // skip leading drive letter
for (p = q; *p; p++) if (*p == '/' || *p == '\\') q = p+1;
return q;
}
void Fl_Window::label(const char *name,const char *iname) {
Fl_Widget::label(name);
iconlabel_ = iname;
if (shown() && !parent()) {
if (!name) name = "";
SetWindowText(i->xid, name);
// if (!iname) iname = fl_filename_name(name);
// should do something with iname here...
}
}
////////////////////////////////////////////////////////////////
// Implement the virtual functions for the base Fl_Window class:
// If the box is a filled rectangle, we can make the redisplay *look*
// faster by using X's background pixel erasing. We can make it
// actually *be* faster by drawing the frame only, this is done by
// setting fl_boxcheat, which is seen by code in fl_drawbox.cxx:
// For WIN32 it looks like all windows share a background color, so
// I use FL_GRAY for this and only do this cheat for windows that are
// that color.
// Actually it is totally disabled.
// Fl_Widget *fl_boxcheat;
//static inline int can_boxcheat(uchar b) {return (b==1 || (b&2) && b<=15);}
void Fl_Window::show() {
image(Fl::scheme_bg_);
if (Fl::scheme_bg_) {
labeltype(FL_NORMAL_LABEL);
align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
} else {
labeltype(FL_NO_LABEL);
}
if (!shown()) {
// if (can_boxcheat(box())) fl_background_pixel = fl_xpixel(color());
Fl_X::make(this);
} else {
// Once again, we would lose the capture if we activated the window.
if (IsIconic(i->xid)) OpenIcon(i->xid);
if (!fl_capture) BringWindowToTop(i->xid);
//ShowWindow(i->xid,fl_capture?SW_SHOWNOACTIVATE:SW_RESTORE);
}
}
Fl_Window *Fl_Window::current_;
// the current context
HDC fl_gc = 0;
// the current window handle, initially set to -1 so we can correctly
// allocate fl_GetDC(0)
HWND fl_window = (HWND)-1;
// Here we ensure only one GetDC is ever in place.
HDC fl_GetDC(HWND w) {
if (fl_gc) {
if (w == fl_window) return fl_gc;
ReleaseDC(fl_window, fl_gc);
}
fl_gc = GetDC(w);
fl_window = w;
// calling GetDC seems to always reset these: (?)
SetTextAlign(fl_gc, TA_BASELINE|TA_LEFT);
SetBkMode(fl_gc, TRANSPARENT);
return fl_gc;
}
// make X drawing go into this window (called by subclass flush() impl.)
void Fl_Window::make_current() {
fl_GetDC(fl_xid(this));
#if USE_COLORMAP
// Windows maintains a hardware and software color palette; the
// SelectPalette() call updates the current soft->hard mapping
// for all drawing calls, so we must select it here before any
// code does any drawing...
fl_select_palette();
#endif // USE_COLORMAP
current_ = this;
fl_clip_region(0);
}
//
// End of "$Id: Fl_win32.cxx,v 1.3 2005/03/30 18:24:34 agno Exp $".
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -