4 #define WIN32_LEAN_AND_MEAN
15 #define CORNER (BORDER * 2)
20 #define BUTTON_OFFSET 2
22 #define NAME_OFFSETX 4
27 #define STATUS_HEIGHT 18
29 #define GRADIENT_SMOOTHNESS 1.0f
31 #define TEXT_COLOR black
34 #define GRADIENT_DIRECTION horizontal
36 static ColorKey gradient[] =
38 { Color { 128, 128, 255}, 0.00f },
39 { Color { 254, 254, 254}, 0.60f },
40 { Color { 0, 0, 255}, 1.00f }
44 #define GRADIENT_DIRECTION vertical
45 static ColorKey gradient[] =
47 { ColorAlpha { 255, { 180, 200, 220} }, 0.00f },
48 { ColorAlpha { 255, { 255, 255, 255} }, 0.60f },
49 { ColorAlpha { 255, { 128, 128, 130} }, 1.00f }
52 static ColorKey gradientInactive[] =
54 { ColorAlpha { 255, { 160, 180, 200} }, 0.00f },
55 { ColorAlpha { 255, { 220, 220, 220} }, 0.60f },
56 { ColorAlpha { 255, { 100, 100, 100} }, 1.00f }
60 #define GRADIENT_DIRECTION horizontal
61 #define TEXT_COLOR white
63 //#define TEXT_INACTIVE Color { 212,208,200 }
64 #define TEXT_INACTIVE Color { 40, 50, 60 }
66 static ColorKey gradient[] =
68 { ColorAlpha { 255, Color { 10, 36, 106 } }, 0.00f },
69 { ColorAlpha { 255, Color { 166, 202, 240 } }, 1.00f }
71 static ColorKey gradientInactive[] =
73 { ColorAlpha { 255, Color { 128, 128, 128 } }, 0.00f },
74 { ColorAlpha { 255, Color { 192, 192, 192 } }, 1.00f }
77 char * cursorsBitmaps[] =
79 "<:ecere>cursors/arrow.png",
80 "<:ecere>cursors/iBeam.png",
81 "<:ecere>cursors/cross.png",
82 "<:ecere>cursors/move.png",
83 "<:ecere>cursors/sizeNorthEastSouthWest.png",
84 "<:ecere>cursors/sizeNorthSouth.png",
85 "<:ecere>cursors/sizeNorthWestSouthEast.png",
86 "<:ecere>cursors/sizeWestEast.png",
87 "<:ecere>cursors/move.png"
90 static Point cursorsHotSpots[] =
102 static char * skinBitmaps[SkinBitmap] =
104 "<:ecere>elements/areaMinimize.png",
105 "<:ecere>elements/areaMaximize.png",
106 "<:ecere>elements/areaRestore.png",
107 "<:ecere>elements/areaClose.png"
110 class WindowsSkin : Skin
112 class_property(name) = "Windows";
113 class_property(selectionColor) = Color { 10, 36, 106 };
114 class_property(selectionText) = (Color)white;
115 class_property(disabledFrontColor) = Color { 128,128,128 };
116 class_property(disabledBackColor) = (Color)white;
118 FontResource ::SystemFont()
120 return FontResource { faceName = "Tahoma", size = 8.25f };
123 FontResource ::CaptionFont()
125 return FontResource { faceName = "Tahoma", size = 8.25f, bold = true };
128 char * ::CursorsBitmaps(uint id, int * hotSpotX, int *hotSpotY, byte ** paletteShades)
130 *hotSpotX = cursorsHotSpots[id].x;
131 *hotSpotY = cursorsHotSpots[id].y;
132 *paletteShades = null;
133 return cursorsBitmaps[id];
136 BitmapResource ::GetBitmap(SkinBitmap id)
138 return BitmapResource { fileName = skinBitmaps[id] };
141 int ::VerticalSBW() { return SB_WIDTH; }
142 int ::HorizontalSBH() { return SB_HEIGHT; }
146 public class WindowsSkin_Window : Window
148 void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h)
152 if(hasMenuBar && state != minimized)
154 *h += skinMenuHeight;
156 if(statusBar && state != minimized)
161 if(nativeDecorations && rootWindow == this)
164 RECT rcClient, rcWindow;
165 GetClientRect(windowHandle, &rcClient);
166 GetWindowRect(windowHandle, &rcWindow);
167 *w += (rcWindow.right - rcWindow.left) - rcClient.right;
168 *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
170 // PrintLn(_class.name, " is at l = ", rcWindow.left, ", r = ", rcWindow.right);
174 if((((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel) && state != minimized)
179 if(((BorderBits)borderStyle).sizable && (state == normal))
184 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
187 if(!((BorderBits)borderStyle).sizable || state == minimized)
193 if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
200 void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh)
202 bool isNormal = (state == normal);
203 if(nativeDecorations && rootWindow == this) return;
204 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
211 if(((BorderBits)borderStyle).sizable && isNormal)
213 // GetDecorationsSize(window, mw, mh);
219 if(hasVertScroll && hasHorzScroll)
221 *mw += 2 * SB_WIDTH + SB_WIDTH;
222 *mh += 2 * SB_HEIGHT + SB_HEIGHT;
223 if(((BorderBits)borderStyle).sizable && isNormal)
228 void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
230 bool isNormal = (state == normal);
231 MinMaxValue aw = 0, ah = 0;
237 *y += skinMenuHeight;
240 GetDecorationsSize(&aw, &ah);
242 if(nativeDecorations && rootWindow == this)
246 POINT client00 = { 0, 0 };
247 ClientToScreen(windowHandle, &client00);
248 GetWindowRect(windowHandle, &rcWindow);
249 *x += client00.x - rcWindow.left;
250 *y += client00.y - rcWindow.top;
255 // Compute client area start
256 if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
262 if(((BorderBits)borderStyle).sizable && isNormal)
268 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
271 if(!((BorderBits)borderStyle).sizable || state == minimized)
278 if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
285 // Reduce client area
293 void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving)
295 bool isNormal = (state == normal);
296 int top = 0, border = 0, bottom = 0;
298 if(nativeDecorations && rootWindow == this) return;
300 if(state == minimized)
301 top = border = bottom = DEAD_BORDER;
302 else if(((BorderBits)borderStyle).sizable)
304 top = isNormal ? TOP : 0;
305 border = isNormal ? BORDER : 0;
308 else if(((BorderBits)borderStyle).fixed)
311 border = DEAD_BORDER;
312 bottom = DEAD_BORDER;
314 else if(((BorderBits)borderStyle).contour)
321 if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
323 int deepTop = 0, deepBottom = 0, deepBorder = 0;
324 if(((BorderBits)borderStyle).contour)
327 deepTop = (((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar)) ? (top + CAPTION) : top;
328 deepBottom = (((BorderBits)borderStyle).sizable && isNormal) ? bottom : border;
331 surface.Bevel(((BorderBits)borderStyle).bevel ? false : true, deepBorder, deepTop,
332 size.w - deepBorder - deepBorder, size.h - deepBottom - deepTop);
335 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
337 if(state != maximized || !((BorderBits)borderStyle).sizable)
339 // Frame for ES_CAPTION windows
340 surface.Bevel(false, 0, 0, size.w, size.h);
341 surface.SetForeground(activeBorder);
342 surface.Rectangle(2, 2, size.w-3, size.h-3);
344 // Resizeable frame is 1 pixel thicker
345 if(((BorderBits)borderStyle).sizable && isNormal)
346 surface.Rectangle(3, 3, size.w - 4, size.h - 4);
351 surface.Gradient(gradient, sizeof(gradient) / sizeof(ColorKey), GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
352 border, top, size.w - border - 1, top + CAPTION - 2);
354 surface.Gradient(gradientInactive, sizeof(gradientInactive) / sizeof(ColorKey),
355 GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
356 border, top, size.w - border - 1, top + CAPTION - 2);
358 surface.SetForeground(activeBorder);
359 if(state != minimized)
360 surface.HLine(border, size.w-border-1, top + CAPTION-1);
362 surface.SetForeground((active ? TEXT_COLOR : TEXT_INACTIVE));
363 surface.TextOpacity(false);
364 surface.TextFont(captionFont);
367 int buttonsSize = border +
368 ((hasMaximize || hasMinimize) ? 52 : 18);
369 surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET,
370 size.w - (buttonsSize + border + 4), name, strlen(name));
373 if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
375 surface.SetForeground(black);
376 surface.Rectangle(0, 0, size.w - 1, size.h - 1);
379 if(state != minimized && hasHorzScroll && hasVertScroll)
381 if(sbh && sbh.visible && sbv && sbv.visible)
383 surface.SetBackground(activeBorder);
385 clientStart.x + clientSize.w,
386 clientStart.y + clientSize.h,
387 clientStart.x + clientSize.w + SB_WIDTH - 1,
388 clientStart.y + clientSize.h + SB_HEIGHT - 1);
393 bool IsMouseMoving(int x, int y, int w, int h)
395 bool isNormal = (state == normal);
397 if(nativeDecorations && rootWindow == this) return false;
399 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
401 int corner = 0, border = 0, top = 0;
402 if(((BorderBits)borderStyle).sizable && isNormal)
408 // Special case for having caption on resize bar
410 result = Box { corner, 0, w-corner-1, TOP-1 }.IsPointInside({x,y});
412 result = Box { border, top, w-border-1, top+CAPTION-1 }.IsPointInside({x, y});
417 bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY)
421 *resizeX = *resizeY = *resizeEndX = *resizeEndY = false;
422 if(nativeDecorations && rootWindow == this) return false;
424 if(((BorderBits)borderStyle).sizable && (state == normal))
427 if(Box { 0, 0,CORNER-1, TOP-1 }.IsPointInside({x, y}))
428 result = *resizeX = *resizeY = true;
430 if(Box { w-CORNER-1, 0, w-1, TOP-1 }.IsPointInside({x, y}))
431 result = *resizeEndX = *resizeY = true;
433 if(Box { 0, h-BOTTOM-1, CORNER-1, h-1 }.IsPointInside({x, y}))
434 result = *resizeX = *resizeEndY = true;
435 // BottomRight Corner
436 if(Box { w-CORNER-1, h-BOTTOM-1, w-1, h-1 }.IsPointInside({x, y}))
437 result = *resizeEndX = *resizeEndY = true;
439 if(Box { 0,TOP, BORDER, h-BOTTOM-1 }.IsPointInside({x, y}))
440 result = *resizeX = true;
442 if(Box { w-BORDER-1, TOP, w-1, h-BOTTOM-1 }.IsPointInside({x, y}))
443 result = *resizeEndX = true;
445 if(Box { CORNER, 0, w-CORNER-1, TOP-1 }.IsPointInside({x, y}))
446 result = *resizeY = true;
448 if(Box { CORNER, h-BOTTOM-1, w-CORNER-1, h-1 }.IsPointInside({x, y}))
449 result = *resizeEndY = true;
454 void UpdateNonClient()
456 bool isNormal = (state == normal);
457 int top = 0, border = 0;
458 int insideBorder = 0;
460 if(!nativeDecorations || rootWindow != this)
462 if(state == minimized)
463 top = border = DEAD_BORDER;
464 else if(((BorderBits)borderStyle).sizable)
466 if(state == maximized && parent.menuBar)
473 top = isNormal ? TOP : 0;
474 border = isNormal ? BORDER : 0;
477 else if(((BorderBits)borderStyle).fixed)
480 border = DEAD_BORDER;
482 else if(((BorderBits)borderStyle).contour)
487 insideBorder = border;
488 if(((BorderBits)borderStyle).deep)
494 if(state == minimized)
495 menuBar.visible = false;
497 menuBar.visible = true;
498 menuBar.Move(clientStart.x, clientStart.y - skinMenuHeight, size.w - insideBorder * 2, skinMenuHeight);
502 if(state == minimized)
503 statusBar.visible = false;
506 statusBar.visible = true;
507 if(nativeDecorations && rootWindow == this)
509 statusBar.anchor = { left = clientStart.x, bottom = (int)(size.h - clientSize.h - clientStart.y - STATUS_HEIGHT ) };
510 statusBar.size.w = size.w - insideBorder * 2;
514 statusBar.anchor = { left = clientStart.x, bottom = border };
515 statusBar.size.w = size.w - insideBorder * 2;
519 if(!nativeDecorations || rootWindow != this)
523 sysButtons[0].anchor = { right = 35 + border, top = top + BUTTON_OFFSET };
524 sysButtons[0].size = { 15, 15 };
525 sysButtons[0].bevel = true;
526 sysButtons[0].bitmap = { skinBitmaps[(state == minimized) ? restore : minimize] };
527 sysButtons[0].visible = true;
531 sysButtons[1].anchor = { right = 20 + border, top = top + BUTTON_OFFSET };
532 sysButtons[1].size = { 15, 15 };
533 sysButtons[1].bevel = true;
534 sysButtons[1].bitmap = { skinBitmaps[(state == maximized) ? restore : maximize] };
535 sysButtons[1].visible = true;
539 sysButtons[2].anchor = { right = 2 + border, top = top + BUTTON_OFFSET };
540 sysButtons[2].size = { 15, 15 };
541 sysButtons[2].bevel = true;
542 sysButtons[2].bitmap = { skinBitmaps[close] };
543 sysButtons[2].visible = true;