From ce49ac905326fa2a992a6fd4ade3e7768fad8ad9 Mon Sep 17 00:00:00 2001 From: Acfboy Date: Mon, 27 Jul 2026 09:04:25 +0800 Subject: [PATCH] examples/microwindows: add mwdemo demo application This ports mwdemo.c from Microwindows as a standalone NuttX example application. mwdemo is the primary Win32 API demo in the Microwindows project, featuring 3D graphics, window controls, timer-driven animation, and bitmap image rendering. The demo runs on both qemu-intel64:mw and sim:mw configurations. Signed-off-by: Acfboy examples/microwindows: address review, clean up mwdemo. - Replace minimal copyright notice with full Apache 2.0 license header - Use angle brackets for system and microwindows includes - Remove OS-specific dead code (DOS_TURBOC, RTEMS, EMSCRIPTEN/MULTIAPP) - Drop unused demo-mode macros and their corresponding dead code paths (IMAGE, CLIENT3D, CLIPDEMO, ARCDEMO). Keep a fixed GRAPH3D+CONTROLS configuration as the single NuttX demo. - Add g_ prefix to global variable (image -> g_image) - Move demoWndData typedef from mid-file to Private Types section - Merge WinMain body into main() and remove the WinMain indirection - Removed unused images. Signed-off-by: Acfboy --- examples/microwindows/Kconfig | 26 +++ examples/microwindows/Make.defs | 25 +++ examples/microwindows/Makefile | 55 +++++ examples/microwindows/mwdemo.c | 333 ++++++++++++++++++++++++++++ examples/microwindows/mwdemo_main.c | 101 +++++++++ 5 files changed, 540 insertions(+) create mode 100644 examples/microwindows/Kconfig create mode 100644 examples/microwindows/Make.defs create mode 100644 examples/microwindows/Makefile create mode 100644 examples/microwindows/mwdemo.c create mode 100644 examples/microwindows/mwdemo_main.c diff --git a/examples/microwindows/Kconfig b/examples/microwindows/Kconfig new file mode 100644 index 000000000..6319ac587 --- /dev/null +++ b/examples/microwindows/Kconfig @@ -0,0 +1,26 @@ +config EXAMPLES_MICROWINDOWS + tristate "Microwindows example" + default n + depends on GRAPHICS_MICROWINDOWS + depends on MICROWINDOWS_MWIN + ---help--- + Enable the Microwindows example application + +if EXAMPLES_MICROWINDOWS + +config EXAMPLES_MICROWINDOWS_PROGNAME + string "Program name" + default "mwexample" + ---help--- + This is the name of the program that will be used when the NSH ELF + program is installed. + +config EXAMPLES_MICROWINDOWS_PRIORITY + int "Microwindows task priority" + default 100 + +config EXAMPLES_MICROWINDOWS_STACKSIZE + int "Microwindows stack size" + default 32768 + +endif diff --git a/examples/microwindows/Make.defs b/examples/microwindows/Make.defs new file mode 100644 index 000000000..6c3595cc3 --- /dev/null +++ b/examples/microwindows/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# apps/examples/microwindows/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_MICROWINDOWS),) +CONFIGURED_APPS += $(APPDIR)/examples/microwindows +endif diff --git a/examples/microwindows/Makefile b/examples/microwindows/Makefile new file mode 100644 index 000000000..c8c588abc --- /dev/null +++ b/examples/microwindows/Makefile @@ -0,0 +1,55 @@ +############################################################################ +# apps/examples/microwindows/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +PROGNAME = $(CONFIG_EXAMPLES_MICROWINDOWS_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_MICROWINDOWS_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_MICROWINDOWS_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_MICROWINDOWS) + +MAINSRC = mwdemo_main.c +CSRCS += mwdemo.c +MW_IMAGES = penguin microwin +CSRCS += $(MW_IMAGES:%=$(MW_IMGDIR)/%.c) + +# Generate image .c files from .bmp +MW_SRC = $(APPDIR)/graphics/microwindows/microwindows/src +MW_IMGDIR = images +MW_CONVBMP = convbmp$(HOSTEXEEXT) + +$(MW_CONVBMP): $(MW_SRC)/images/tools/convbmp.c + $(HOSTCC) $(HOSTCFLAGS) -I$(MW_SRC)/include $< -o $@ + +$(MW_IMGDIR)/%.c: $(MW_SRC)/images/demos/mwin/%.bmp $(MW_CONVBMP) + mkdir -p $(MW_IMGDIR) + $(CURDIR)/$(MW_CONVBMP) -o $@ $< + +clean:: + $(call DELFILE, $(MW_IMAGES:%=$(MW_IMGDIR)/%.c)) + $(Q) rmdir $(MW_IMGDIR) 2>/dev/null || true + $(call DELFILE, $(MW_CONVBMP)) + +CFLAGS += -Wno-undef +CFLAGS += -DNOGDI + +include $(APPDIR)/Application.mk diff --git a/examples/microwindows/mwdemo.c b/examples/microwindows/mwdemo.c new file mode 100644 index 000000000..c672fd459 --- /dev/null +++ b/examples/microwindows/mwdemo.c @@ -0,0 +1,333 @@ +/**************************************************************************** + * apps/examples/microwindows/mwdemo.c + * + * Copyright (c) 1999, 2000, 2001, 2010 Greg Haerr + * Portions Copyright (c) 2002 by Koninklijke Philips Electronics N.V. + * + * Demo program for Microwindows + * + * GB: 10-14-2004: Modified to store degrees data on each window, + * for new Timers features. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#define MWINCLUDECOLORS +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef struct +{ + int startdegrees; + int enddegrees; +} demoWndData; + +typedef demoWndData *pdemoWndData; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +extern MWIMAGEHDR image_penguin; +PMWIMAGEHDR g_image = &image_penguin; + +#define APPCLASS "test" +#define APPCHILD "test2" + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp); + +LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +int MwUserInit(int ac, char **av) +{ + /* test user init procedure - do nothing */ + + return 0; +} + +int RegisterAppClass(HINSTANCE hInstance) +{ + WNDCLASS wc; + + /* register builtin controls and dialog classes */ + + MwInitializeDialogs(hInstance); + + wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(LONG_PTR); + wc.hInstance = 0; + wc.hIcon = 0; /* LoadIcon(GetHInstance(), MAKEINTRESOURCE( + * 1)); */ + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = APPCLASS; + RegisterClass(&wc); + + wc.lpfnWndProc = (WNDPROC) ChildWndProc; + wc.lpszClassName = APPCHILD; + return RegisterClass(&wc); +} + +HWND CreateAppWindow(void) +{ + HWND hwnd; + static int nextid = 1; + int width; + int height; + RECT r; + GetWindowRect(GetDesktopWindow(), &r); + width = height = r.right / 2; + + hwnd = CreateWindowEx(0L, APPCLASS, + "Microwindows Application", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + width, height, + NULL, (HMENU)(LONG_PTR)nextid++, NULL, NULL); + + if (hwnd && (nextid & 03) != 2) + { + CreateWindowEx(0L, APPCHILD, + "", + WS_BORDER | WS_CHILD | WS_VISIBLE, + 4, 4, width / 3 - 6, height / 3, + hwnd, (HMENU)2, NULL, NULL); + CreateWindowEx(0L, APPCHILD, + "", + WS_BORDER | WS_CHILD | WS_VISIBLE, + width / 3, height / 3, + width / 3 - 6, height / 3, + hwnd, (HMENU)3, NULL, NULL); + CreateWindowEx(0L, APPCHILD, + "", + WS_BORDER | WS_CHILD | WS_VISIBLE, + width * 3 / 5, height * 3 / 5, + width * 2 / 3, height * 2 / 3, + hwnd, (HMENU)4, NULL, NULL); + CreateWindowEx(0L, "EDIT", + "OK", + WS_BORDER | WS_CHILD | WS_VISIBLE, + width * 5 / 8, 10, + 100, 18, + hwnd, (HMENU)5, NULL, NULL); + CreateWindowEx(0L, "PROGBAR", + "OK", + WS_BORDER | WS_CHILD | WS_VISIBLE, + width * 5 / 8, 32, + 100, 18, + hwnd, (HMENU)6, NULL, NULL); + + HWND hlist = CreateWindowEx(0L, "LISTBOX", + "OK", + WS_HSCROLL | WS_VSCROLL | + WS_BORDER | WS_CHILD | + WS_VISIBLE, + width * 5 / 8, 54, + 100, 48, + hwnd, (HMENU)7, NULL, NULL); + SendMessage(hlist, LB_ADDSTRING, 0, + (LPARAM)(LPSTR)"Cherry"); + SendMessage(hlist, LB_ADDSTRING, 0, + (LPARAM)(LPSTR)"Apple"); + SendMessage(hlist, LB_ADDSTRING, 0, + (LPARAM)(LPSTR)"Orange"); + + CreateWindowEx(0L, "BUTTON", + "Cancel", + BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, + width * 5 / 8 + 50, 106, + 50, 14, + hwnd, (HMENU)8, NULL, NULL); + } + + return hwnd; +} + +LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + RECT rc; + PAINTSTRUCT ps; + + switch (msg) + { + case WM_PAINT: + BeginPaint(hwnd, &ps); + GetClientRect(hwnd, &rc); + + HDC hdcMem; + HBITMAP hbmp, hbmpOrg; + + /* redirect painting to offscreen dc, then use blit function */ + + hdcMem = CreateCompatibleDC(ps.hdc); + + /* Note: rc.right, rc.bottom happens to be smaller than image + * width/height. We use the image size, so we can stretchblit + * from the whole image. + */ + + hbmp = CreateCompatibleBitmap(hdcMem, g_image->width, + g_image->height); + hbmpOrg = SelectObject(hdcMem, hbmp); + + /* draw onto offscreen dc */ + + DrawDIB(hdcMem, 0, 0, g_image); + + /* blit offscreen with physical screen */ + + StretchBlt(ps.hdc, 0, 0, rc.right * 4 / 5, + rc.bottom * 4 / 5, hdcMem, + 0, 0, g_image->width, g_image->height, MWROP_COPY); + DeleteObject(SelectObject(hdcMem, hbmpOrg)); + DeleteDC(hdcMem); + EndPaint(hwnd, &ps); + break; + default: + return DefWindowProc(hwnd, msg, wp, lp); + } + + return 0; +} + +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + PAINTSTRUCT ps; + HDC hdc; + RECT rc; + static int countup = 1; + int id; + static vec1 gx; + static vec1 gy; + static POINT mousept; + pdemoWndData pData; + + switch (msg) + { + case WM_CREATE: + pData = (pdemoWndData) malloc(sizeof(demoWndData)); + SetWindowLongPtr(hwnd, 0, (LONG_PTR) pData); + mousept.x = 60; + mousept.y = 20; + pData->startdegrees = 0; + pData->enddegrees = 30; + SetTimer(hwnd, 1, (50 + random() % 250), NULL); + break; + + case WM_TIMER: + pData = (pdemoWndData)(LONG_PTR)GetWindowLongPtr(hwnd, 0); + GetClientRect(hwnd, &rc); + if (countup) + { + mousept.y += 20; + if (mousept.y >= rc.bottom) + { + mousept.y -= 20; + countup = 0; + } + } + else + { + mousept.y -= 20; + if (mousept.y < 20) + { + mousept.y += 20; + countup = 1; + } + } + + SendMessage(hwnd, WM_MOUSEMOVE, 0, + MAKELONG(mousept.x, mousept.y)); + break; + case WM_DESTROY: + KillTimer(hwnd, 1); + pData = (pdemoWndData)(LONG_PTR)GetWindowLongPtr(hwnd, 0); + free(pData); + SetWindowLongPtr(hwnd, 0, (LONG_PTR)0); + break; + case WM_SIZE: + break; + case WM_MOVE: + break; + + case WM_ERASEBKGND: + if ((GetWindowLong(hwnd, GWL_ID) & 03) == 1) + { + return 1; + } + + return DefWindowProc(hwnd, msg, wp, lp); + case WM_PAINT: + hdc = BeginPaint(hwnd, &ps); + id = (int)GetWindowLong(hwnd, GWL_ID) & 03; + init3(hdc, id == 1 ? hwnd : NULL); + switch (id) + { + case 0: + rose(1.0, 7, 13); + break; + case 1: + look3(-2 * gx, -2 * gy, 1.2); + drawgrid(-8.0, 8.0, 10, -8.0, 8.0, 10); + break; + case 2: + setcolor3(BLACK); + circle3(1.0); + break; + case 3: + setcolor3(BLUE); + daisy(1.0, 20); + break; + } + + paint3(hdc); + EndPaint(hwnd, &ps); + break; + + case WM_MOUSEMOVE: + pData = (pdemoWndData)(LONG_PTR)GetWindowLongPtr(hwnd, 0); + if ((GetWindowLong(hwnd, GWL_ID) & 03) == 1) + { + POINT pt; + + POINTSTOPOINT(pt, lp); + GetClientRect(hwnd, &rc); + gx = (vec1) pt.x / rc.right; + gy = (vec1) pt.y / rc.bottom; + InvalidateRect(hwnd, NULL, FALSE); + mousept.x = pt.x; + mousept.y = pt.y; + } + break; + case WM_LBUTTONDOWN: + break; + case WM_LBUTTONUP: + break; + case WM_RBUTTONDOWN: + break; + default: + return DefWindowProc(hwnd, msg, wp, lp); + } + + return 0; +} diff --git a/examples/microwindows/mwdemo_main.c b/examples/microwindows/mwdemo_main.c new file mode 100644 index 000000000..f8860074b --- /dev/null +++ b/examples/microwindows/mwdemo_main.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * apps/examples/microwindows/mwdemo_main.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +extern MWIMAGEHDR image_microwin; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +extern int RegisterAppClass(HINSTANCE hInstance); +extern HWND CreateAppWindow(void); + +#define APPCLASS "test" +#define APPCHILD "test2" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + MSG msg; + HWND hwnd; + RECT rc; + + invoke_WinMain_Start(argc, argv); + + srandom(time(NULL)); + RegisterAppClass(0); + GetWindowRect(GetDesktopWindow(), &rc); + + /* create penguin window */ + + CreateWindowEx(0L, APPCHILD, "", + WS_BORDER | WS_VISIBLE, + rc.right - 130 - 1, rc.bottom - 153 - 1, + 130, 153, + GetDesktopWindow(), (HMENU)1000, NULL, NULL); + + CreateAppWindow(); + CreateAppWindow(); + CreateAppWindow(); + CreateAppWindow(); + CreateAppWindow(); + CreateAppWindow(); + CreateAppWindow(); + CreateAppWindow(); + + /* set background wallpaper */ + + MwSetDesktopWallpaper(&image_microwin); + hwnd = CreateAppWindow(); + GetWindowRect(hwnd, &rc); + OffsetRect(&rc, 50, 50); + MoveWindow(hwnd, rc.left, rc.top, + rc.bottom - rc.top, + rc.right - rc.left, TRUE); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + invoke_WinMain_End(); + + return 0; +}