3 #define WIN32_LEAN_AND_MEAN
13 #define CORNER (BORDER * 2)
18 #define BUTTON_OFFSET 2
20 #define NAME_OFFSETX 4
25 #define STATUS_HEIGHT 18
27 #define GRADIENT_SMOOTHNESS 1.0f
29 #define TEXT_COLOR black
32 #define GRADIENT_DIRECTION horizontal
34 static ColorKey gradient[] =
36 { Color { 128, 128, 255}, 0.00f },
37 { Color { 254, 254, 254}, 0.60f },
38 { Color { 0, 0, 255}, 1.00f }
42 #define GRADIENT_DIRECTION vertical
43 static ColorKey gradient[] =
45 { ColorAlpha { 255, { 180, 200, 220} }, 0.00f },
46 { ColorAlpha { 255, { 255, 255, 255} }, 0.60f },
47 { ColorAlpha { 255, { 128, 128, 130} }, 1.00f }
50 static ColorKey gradientInactive[] =
52 { ColorAlpha { 255, { 160, 180, 200} }, 0.00f },
53 { ColorAlpha { 255, { 220, 220, 220} }, 0.60f },
54 { ColorAlpha { 255, { 100, 100, 100} }, 1.00f }
58 #define GRADIENT_DIRECTION horizontal
59 #define TEXT_COLOR white
61 //#define TEXT_INACTIVE Color { 212,208,200 }
62 #define TEXT_INACTIVE Color { 40, 50, 60 }
64 static ColorKey gradient[] =
66 { ColorAlpha { 255, Color { 10, 36, 106 } }, 0.00f },
67 { ColorAlpha { 255, Color { 166, 202, 240 } }, 1.00f }
69 static ColorKey gradientInactive[] =
71 { ColorAlpha { 255, Color { 128, 128, 128 } }, 0.00f },
72 { ColorAlpha { 255, Color { 192, 192, 192 } }, 1.00f }
75 char * cursorsBitmaps[] =
77 "<:ecere>cursors/arrow.png",
78 "<:ecere>cursors/iBeam.png",
79 "<:ecere>cursors/cross.png",
80 "<:ecere>cursors/move.png",
81 "<:ecere>cursors/sizeNorthEastSouthWest.png",
82 "<:ecere>cursors/sizeNorthSouth.png",
83 "<:ecere>cursors/sizeNorthWestSouthEast.png",
84 "<:ecere>cursors/sizeWestEast.png",
85 "<:ecere>cursors/move.png"
88 static Point cursorsHotSpots[] =
100 static char * skinBitmaps[SkinBitmap] =
102 "<:ecere>elements/areaMinimize.png",
103 "<:ecere>elements/areaMaximize.png",
104 "<:ecere>elements/areaRestore.png",
105 "<:ecere>elements/areaClose.png"
108 class WindowsSkin : Skin
110 class_property(name) = "Windows";
111 class_property(selectionColor) = Color { 10, 36, 106 };
112 class_property(selectionText) = (Color)white;
113 class_property(disabledFrontColor) = Color { 128,128,128 };
114 class_property(disabledBackColor) = (Color)white;
116 FontResource ::SystemFont()
118 return FontResource { faceName = "Tahoma", size = 8.25f };
121 FontResource ::CaptionFont()
123 return FontResource { faceName = "Tahoma", size = 8.25f, bold = true };
126 char * ::CursorsBitmaps(uint id, int * hotSpotX, int *hotSpotY, byte ** paletteShades)
128 *hotSpotX = cursorsHotSpots[id].x;
129 *hotSpotY = cursorsHotSpots[id].y;
130 *paletteShades = null;
131 return cursorsBitmaps[id];
134 BitmapResource ::GetBitmap(SkinBitmap id)
136 return BitmapResource { fileName = skinBitmaps[id] };
139 int ::VerticalSBW() { return SB_WIDTH; }
140 int ::HorizontalSBH() { return SB_HEIGHT; }
144 public class WindowsSkin_Window : Window
146 void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h)
150 if(hasMenuBar && state != minimized)
152 *h += skinMenuHeight;
154 if(statusBar && state != minimized)
159 if(nativeDecorations && rootWindow == this)
162 RECT rcClient, rcWindow;
163 GetClientRect(windowHandle, &rcClient);
164 GetWindowRect(windowHandle, &rcWindow);
165 if(state == maximized)
167 *w += (rcWindow.right - rcWindow.left) - rcClient.right;
168 *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
172 *w += (rcWindow.right - rcWindow.left) - rcClient.right;
173 *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
178 if((((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel) && state != minimized)
183 if(((BorderBits)borderStyle).sizable && (state == normal))
188 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
191 if(!((BorderBits)borderStyle).sizable || state == minimized)
197 if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
204 void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh)
206 bool isNormal = (state == normal);
207 if(nativeDecorations && rootWindow == this) return;
208 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
215 if(((BorderBits)borderStyle).sizable && isNormal)
217 // GetDecorationsSize(window, mw, mh);
223 if(hasVertScroll && hasHorzScroll)
225 *mw += 2 * SB_WIDTH + SB_WIDTH;
226 *mh += 2 * SB_HEIGHT + SB_HEIGHT;
227 if(((BorderBits)borderStyle).sizable && isNormal)
232 void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
234 bool isNormal = (state == normal);
235 MinMaxValue aw = 0, ah = 0;
241 *y += skinMenuHeight;
244 GetDecorationsSize(&aw, &ah);
246 if(nativeDecorations && rootWindow == this)
250 POINT client00 = { 0, 0 };
251 ClientToScreen(windowHandle, &client00);
252 GetWindowRect(windowHandle, &rcWindow);
253 *x += client00.x - rcWindow.left;
254 *y += client00.y - rcWindow.top;
259 // Compute client area start
260 if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
266 if(((BorderBits)borderStyle).sizable && isNormal)
272 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
275 if(!((BorderBits)borderStyle).sizable || state == minimized)
282 if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
289 // Reduce client area
297 void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving)
299 bool isNormal = (state == normal);
300 int top = 0, border = 0, bottom = 0;
302 if(nativeDecorations && rootWindow == this) return;
304 if(state == minimized)
305 top = border = bottom = DEAD_BORDER;
306 else if(((BorderBits)borderStyle).sizable)
308 top = isNormal ? TOP : 0;
309 border = isNormal ? BORDER : 0;
312 else if(((BorderBits)borderStyle).fixed)
315 border = DEAD_BORDER;
316 bottom = DEAD_BORDER;
318 else if(((BorderBits)borderStyle).contour)
325 if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
327 int deepTop = 0, deepBottom = 0, deepBorder = 0;
328 if(((BorderBits)borderStyle).contour)
331 deepTop = (((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar)) ? (top + CAPTION) : top;
332 deepBottom = (((BorderBits)borderStyle).sizable && isNormal) ? bottom : border;
335 surface.Bevel(((BorderBits)borderStyle).bevel ? false : true, deepBorder, deepTop,
336 size.w - deepBorder - deepBorder, size.h - deepBottom - deepTop);
339 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
341 if(state != maximized || !((BorderBits)borderStyle).sizable)
343 // Frame for ES_CAPTION windows
344 surface.Bevel(false, 0, 0, size.w, size.h);
345 surface.SetForeground(activeBorder);
346 surface.Rectangle(2, 2, size.w-3, size.h-3);
348 // Resizeable frame is 1 pixel thicker
349 if(((BorderBits)borderStyle).sizable && isNormal)
350 surface.Rectangle(3, 3, size.w - 4, size.h - 4);
355 surface.Gradient(gradient, sizeof(gradient) / sizeof(ColorKey), GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
356 border, top, size.w - border - 1, top + CAPTION - 2);
358 surface.Gradient(gradientInactive, sizeof(gradientInactive) / sizeof(ColorKey),
359 GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
360 border, top, size.w - border - 1, top + CAPTION - 2);
362 surface.SetForeground(activeBorder);
363 if(state != minimized)
364 surface.HLine(border, size.w-border-1, top + CAPTION-1);
366 surface.SetForeground((active ? TEXT_COLOR : TEXT_INACTIVE));
367 surface.TextOpacity(false);
368 surface.TextFont(captionFont);
371 int buttonsSize = border +
372 ((hasMaximize || hasMinimize) ? 52 : 18);
373 surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET,
374 size.w - (buttonsSize + border + 4), name, strlen(name));
377 if(((BorderBits)borderStyle).contour && !((BorderBits)borderStyle).fixed)
379 surface.SetForeground(black);
380 surface.Rectangle(0, 0, size.w - 1, size.h - 1);
383 if(state != minimized && hasHorzScroll && hasVertScroll)
385 if(sbh && sbh.visible && sbv && sbv.visible)
387 surface.SetBackground(activeBorder);
389 clientStart.x + clientSize.w,
390 clientStart.y + clientSize.h,
391 clientStart.x + clientSize.w + SB_WIDTH - 1,
392 clientStart.y + clientSize.h + SB_HEIGHT - 1);
397 bool IsMouseMoving(int x, int y, int w, int h)
399 bool isNormal = (state == normal);
401 if(nativeDecorations && rootWindow == this) return false;
403 if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
405 int corner = 0, border = 0, top = 0;
406 if(((BorderBits)borderStyle).sizable && isNormal)
412 // Special case for having caption on resize bar
414 result = Box { corner, 0, w-corner-1, TOP-1 }.IsPointInside({x,y});
416 result = Box { border, top, w-border-1, top+CAPTION-1 }.IsPointInside({x, y});
421 bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY)
425 *resizeX = *resizeY = *resizeEndX = *resizeEndY = false;
426 if(nativeDecorations && rootWindow == this) return false;
428 if(((BorderBits)borderStyle).sizable && (state == normal))
431 if(Box { 0, 0,CORNER-1, TOP-1 }.IsPointInside({x, y}))
432 result = *resizeX = *resizeY = true;
434 if(Box { w-CORNER-1, 0, w-1, TOP-1 }.IsPointInside({x, y}))
435 result = *resizeEndX = *resizeY = true;
437 if(Box { 0, h-BOTTOM-1, CORNER-1, h-1 }.IsPointInside({x, y}))
438 result = *resizeX = *resizeEndY = true;
439 // BottomRight Corner
440 if(Box { w-CORNER-1, h-BOTTOM-1, w-1, h-1 }.IsPointInside({x, y}))
441 result = *resizeEndX = *resizeEndY = true;
443 if(Box { 0,TOP, BORDER, h-BOTTOM-1 }.IsPointInside({x, y}))
444 result = *resizeX = true;
446 if(Box { w-BORDER-1, TOP, w-1, h-BOTTOM-1 }.IsPointInside({x, y}))
447 result = *resizeEndX = true;
449 if(Box { CORNER, 0, w-CORNER-1, TOP-1 }.IsPointInside({x, y}))
450 result = *resizeY = true;
452 if(Box { CORNER, h-BOTTOM-1, w-CORNER-1, h-1 }.IsPointInside({x, y}))
453 result = *resizeEndY = true;
458 void UpdateNonClient()
460 bool isNormal = (state == normal);
461 int top = 0, border = 0;
462 int insideBorder = 0;
464 if(!nativeDecorations && rootWindow == this)
466 if(state == minimized)
467 top = border = DEAD_BORDER;
468 else if(((BorderBits)borderStyle).sizable)
470 if(state == maximized && parent.menuBar)
477 top = isNormal ? TOP : 0;
478 border = isNormal ? BORDER : 0;
481 else if(((BorderBits)borderStyle).fixed)
484 border = DEAD_BORDER;
486 else if(((BorderBits)borderStyle).contour)
491 insideBorder = border;
492 if(((BorderBits)borderStyle).deep)
498 if(state == minimized)
499 menuBar.visible = false;
501 menuBar.visible = true;
502 menuBar.Move(clientStart.x, clientStart.y - skinMenuHeight, size.w - insideBorder * 2, skinMenuHeight);
506 if(state == minimized)
507 statusBar.visible = false;
510 statusBar.visible = true;
511 if(nativeDecorations && rootWindow == this)
513 statusBar.anchor = { left = clientStart.x, bottom = (int)(size.h - clientSize.h - clientStart.y - STATUS_HEIGHT ) };
514 statusBar.size.w = size.w - insideBorder * 2;
518 statusBar.anchor = { left = clientStart.x, bottom = border };
519 statusBar.size.w = size.w - insideBorder * 2;
523 if(!nativeDecorations && rootWindow == this)
527 sysButtons[0].anchor = { right = 35 + border, top = top + BUTTON_OFFSET };
528 sysButtons[0].size = { 15, 15 };
529 sysButtons[0].bevel = true;
530 sysButtons[0].bitmap = { skinBitmaps[(state == minimized) ? restore : minimize] };
531 sysButtons[0].visible = true;
535 sysButtons[1].anchor = { right = 20 + border, top = top + BUTTON_OFFSET };
536 sysButtons[1].size = { 15, 15 };
537 sysButtons[1].bevel = true;
538 sysButtons[1].bitmap = { skinBitmaps[(state == maximized) ? restore : maximize] };
539 sysButtons[1].visible = true;
543 sysButtons[2].anchor = { right = 2 + border, top = top + BUTTON_OFFSET };
544 sysButtons[2].size = { 15, 15 };
545 sysButtons[2].bevel = true;
546 sysButtons[2].bitmap = { skinBitmaps[close] };
547 sysButtons[2].visible = true;