mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 09:04:39 +00:00
Created new application template dialog for testing and demonstration.
svn path=/trunk/; revision=3400
This commit is contained in:
parent
7a3564314a
commit
58bbc5be5d
11 changed files with 924 additions and 0 deletions
16
rosapps/templates/dialog/.cvsignore
Normal file
16
rosapps/templates/dialog/.cvsignore
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
*.sys
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.cpl
|
||||||
|
*.a
|
||||||
|
*.o
|
||||||
|
*.d
|
||||||
|
*.coff
|
||||||
|
*.dsp
|
||||||
|
*.dsw
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opt
|
||||||
|
*.sym
|
||||||
|
*.plg
|
||||||
|
*.bak
|
211
rosapps/templates/dialog/dialog.c
Normal file
211
rosapps/templates/dialog/dialog.c
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* ReactOS Standard Dialog Application Template
|
||||||
|
*
|
||||||
|
* dialog.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_MSG_PUMP_
|
||||||
|
|
||||||
|
typedef struct tagDialogData {
|
||||||
|
HWND hWnd;
|
||||||
|
LONG lData;
|
||||||
|
} DialogData;
|
||||||
|
|
||||||
|
HINSTANCE hInst;
|
||||||
|
HWND hTabWnd;
|
||||||
|
HWND hPage1;
|
||||||
|
HWND hPage2;
|
||||||
|
HWND hPage3;
|
||||||
|
|
||||||
|
LRESULT CreateMemoryDialog(HINSTANCE, HWND hwndOwner, LPSTR lpszMessage);
|
||||||
|
LRESULT CALLBACK PageWndProc1(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
LRESULT CALLBACK PageWndProc2(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
LRESULT CALLBACK PageWndProc3(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static BOOL OnCreate(HWND hWnd, LONG lData)
|
||||||
|
{
|
||||||
|
TCHAR szTemp[256];
|
||||||
|
TCITEM item;
|
||||||
|
|
||||||
|
// Initialize the Windows Common Controls DLL
|
||||||
|
#ifdef __GNUC__
|
||||||
|
InitCommonControls();
|
||||||
|
#else
|
||||||
|
INITCOMMONCONTROLSEX ex = { sizeof(INITCOMMONCONTROLSEX), ICC_TAB_CLASSES };
|
||||||
|
InitCommonControlsEx(&ex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Create tab pages
|
||||||
|
hTabWnd = GetDlgItem(hWnd, IDC_TAB);
|
||||||
|
hPage1 = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PAGE1), hWnd, (DLGPROC)PageWndProc1);
|
||||||
|
hPage2 = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PAGE2), hWnd, (DLGPROC)PageWndProc2);
|
||||||
|
hPage3 = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PAGE3), hWnd, (DLGPROC)PageWndProc3);
|
||||||
|
|
||||||
|
// Insert tabs
|
||||||
|
_tcscpy(szTemp, _T("Page One"));
|
||||||
|
memset(&item, 0, sizeof(TCITEM));
|
||||||
|
item.mask = TCIF_TEXT;
|
||||||
|
item.pszText = szTemp;
|
||||||
|
TabCtrl_InsertItem(hTabWnd, 0, &item);
|
||||||
|
_tcscpy(szTemp, _T("Page Two"));
|
||||||
|
memset(&item, 0, sizeof(TCITEM));
|
||||||
|
item.mask = TCIF_TEXT;
|
||||||
|
item.pszText = szTemp;
|
||||||
|
TabCtrl_InsertItem(hTabWnd, 1, &item);
|
||||||
|
_tcscpy(szTemp, _T("Page Three"));
|
||||||
|
memset(&item, 0, sizeof(TCITEM));
|
||||||
|
item.mask = TCIF_TEXT;
|
||||||
|
item.pszText = szTemp;
|
||||||
|
TabCtrl_InsertItem(hTabWnd, 2, &item);
|
||||||
|
|
||||||
|
ShowWindow(hPage1, SW_SHOW);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTabWndSelChange(void)
|
||||||
|
{
|
||||||
|
switch (TabCtrl_GetCurSel(hTabWnd)) {
|
||||||
|
case 0:
|
||||||
|
ShowWindow(hPage1, SW_SHOW);
|
||||||
|
ShowWindow(hPage2, SW_HIDE);
|
||||||
|
ShowWindow(hPage3, SW_HIDE);
|
||||||
|
BringWindowToTop(hPage1);
|
||||||
|
SetFocus(hTabWnd);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ShowWindow(hPage1, SW_HIDE);
|
||||||
|
ShowWindow(hPage2, SW_SHOW);
|
||||||
|
ShowWindow(hPage3, SW_HIDE);
|
||||||
|
BringWindowToTop(hPage2);
|
||||||
|
SetFocus(hTabWnd);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ShowWindow(hPage1, SW_HIDE);
|
||||||
|
ShowWindow(hPage2, SW_HIDE);
|
||||||
|
ShowWindow(hPage3, SW_SHOW);
|
||||||
|
BringWindowToTop(hPage3);
|
||||||
|
SetFocus(hTabWnd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
int idctrl;
|
||||||
|
LPNMHDR pnmh;
|
||||||
|
LPCREATESTRUCT lpCS;
|
||||||
|
LONG nThisApp = 0;
|
||||||
|
DialogData* pData = (DialogData*)GetWindowLong(hDlg, DWL_USER);
|
||||||
|
if (pData) nThisApp = pData->lData;
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
|
||||||
|
case WM_CREATE:
|
||||||
|
lpCS = (LPCREATESTRUCT)lParam;
|
||||||
|
assert(lpCS);
|
||||||
|
lpCS->style &= ~WS_POPUP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
pData = (DialogData*)lParam;
|
||||||
|
SetWindowLong(hDlg, DWL_USER, (LONG)pData);
|
||||||
|
if (pData) nThisApp = pData->lData;
|
||||||
|
return OnCreate(hDlg, nThisApp);
|
||||||
|
|
||||||
|
#ifdef _USE_MSG_PUMP_
|
||||||
|
case WM_DESTROY:
|
||||||
|
if (pData && (pData->hWnd == hDlg)) {
|
||||||
|
pData->hWnd = 0;
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam)) {
|
||||||
|
case IDOK:
|
||||||
|
//MessageBox(NULL, _T("Good-bye"), _T("dialog"), MB_ICONEXCLAMATION);
|
||||||
|
CreateMemoryDialog(hInst, GetDesktopWindow(), "DisplayMyMessage");
|
||||||
|
case IDCANCEL:
|
||||||
|
if (pData && (pData->hWnd == hDlg)) {
|
||||||
|
DestroyWindow(pData->hWnd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case WM_COMMAND:
|
||||||
|
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
|
||||||
|
EndDialog(hDlg, LOWORD(wParam));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case WM_NOTIFY:
|
||||||
|
idctrl = (int)wParam;
|
||||||
|
pnmh = (LPNMHDR)lParam;
|
||||||
|
if ((pnmh->hwndFrom == hTabWnd) &&
|
||||||
|
(pnmh->idFrom == IDC_TAB) &&
|
||||||
|
(pnmh->code == TCN_SELCHANGE))
|
||||||
|
{
|
||||||
|
OnTabWndSelChange();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int APIENTRY WinMain(HINSTANCE hInstance,
|
||||||
|
HINSTANCE hPrevInstance,
|
||||||
|
LPSTR lpCmdLine,
|
||||||
|
int nCmdShow)
|
||||||
|
{
|
||||||
|
#ifdef _USE_MSG_PUMP_
|
||||||
|
MSG msg;
|
||||||
|
HACCEL hAccel;
|
||||||
|
DialogData instData = { NULL, 34 };
|
||||||
|
|
||||||
|
hInst = hInstance;
|
||||||
|
instData.hWnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_TABBED_DIALOG), NULL, (DLGPROC)DlgProc, (LPARAM)&instData);
|
||||||
|
ShowWindow(instData.hWnd, SW_SHOW);
|
||||||
|
hAccel = LoadAccelerators(hInst, (LPCTSTR)IDR_ACCELERATOR);
|
||||||
|
while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
|
||||||
|
if (!TranslateAccelerator(msg.hwnd, hAccel, &msg)) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
hInst = hInstance;
|
||||||
|
DialogBox(hInst, (LPCTSTR)IDD_TABBED_DIALOG, NULL, (DLGPROC)DlgProc);
|
||||||
|
//CreateMemoryDialog(hInst, GetDesktopWindow(), "CreateMemoryDialog");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
109
rosapps/templates/dialog/dialog.rc
Normal file
109
rosapps/templates/dialog/dialog.rc
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
//Microsoft Developer Studio generated resource script.
|
||||||
|
//
|
||||||
|
#include "resrc1.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "defines.h"
|
||||||
|
#include "reactos\resource.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// English (Australia) resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
|
||||||
|
#ifdef _WIN32
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
|
||||||
|
#pragma code_page(1252)
|
||||||
|
#endif //_WIN32
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Dialog
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_TABBED_DIALOG DIALOG DISCARDABLE 0, 0, 243, 230
|
||||||
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
|
CAPTION "TabTest Dialog"
|
||||||
|
FONT 8, "MS Sans Serif"
|
||||||
|
BEGIN
|
||||||
|
DEFPUSHBUTTON "OK",IDOK,83,207,50,14
|
||||||
|
PUSHBUTTON "Cancel",IDCANCEL,186,207,50,14
|
||||||
|
CONTROL "Tab1",IDC_TAB,"SysTabControl32",0x0,7,7,229,190
|
||||||
|
END
|
||||||
|
|
||||||
|
IDD_PAGE1 DIALOG DISCARDABLE 10, 20, 180, 144
|
||||||
|
STYLE DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN
|
||||||
|
FONT 8, "MS Sans Serif"
|
||||||
|
BEGIN
|
||||||
|
PUSHBUTTON "Button1",IDC_BUTTON1,12,108,62,16
|
||||||
|
LISTBOX IDC_LIST1,7,4,166,98,LBS_OWNERDRAWFIXED | LBS_HASSTRINGS |
|
||||||
|
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||||
|
END
|
||||||
|
|
||||||
|
IDD_PAGE2 DIALOG DISCARDABLE 10, 20, 180, 144
|
||||||
|
STYLE DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN
|
||||||
|
FONT 8, "MS Sans Serif"
|
||||||
|
BEGIN
|
||||||
|
CONTROL "Check1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX |
|
||||||
|
WS_TABSTOP,26,48,123,9
|
||||||
|
END
|
||||||
|
|
||||||
|
IDD_PAGE3 DIALOG DISCARDABLE 10, 20, 180, 144
|
||||||
|
STYLE DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN
|
||||||
|
FONT 8, "MS Sans Serif"
|
||||||
|
BEGIN
|
||||||
|
GROUPBOX "Static",IDC_STATIC,7,7,159,70
|
||||||
|
CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH |
|
||||||
|
TBS_NOTICKS | WS_TABSTOP,40,30,92,17
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"resrc1.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"#include ""defines.h""\r\n"
|
||||||
|
"#include ""reactos\\resource.h""\r\n"
|
||||||
|
"#include ""resource.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE DISCARDABLE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
#endif // English (Australia) resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
34
rosapps/templates/dialog/makefile
Normal file
34
rosapps/templates/dialog/makefile
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# $Id: makefile,v 1.1 2002/08/27 00:53:34 robd Exp $
|
||||||
|
|
||||||
|
PATH_TO_TOP = ../../../reactos
|
||||||
|
|
||||||
|
TOOLS_PATH = $(PATH_TO_TOP)/tools
|
||||||
|
|
||||||
|
TARGET_TYPE = program
|
||||||
|
|
||||||
|
TARGET_APPTYPE = windows
|
||||||
|
|
||||||
|
TARGET_NAME = dialog
|
||||||
|
|
||||||
|
TARGET_SDKLIBS = ntdll.a kernel32.a user32.a gdi32.a
|
||||||
|
|
||||||
|
TARGET_GCCLIBS = advapi32 comctl32 comdlg32 version
|
||||||
|
|
||||||
|
TARGET_OBJECTS = $(TARGET_NAME).o \
|
||||||
|
memdlg.o \
|
||||||
|
page1.o \
|
||||||
|
page2.o \
|
||||||
|
page3.o \
|
||||||
|
trace.o
|
||||||
|
|
||||||
|
TARGET_CLEAN = $(TARGET_OBJECTS)
|
||||||
|
|
||||||
|
include $(PATH_TO_TOP)/rules.mak
|
||||||
|
|
||||||
|
include $(TOOLS_PATH)/helper.mk
|
||||||
|
|
||||||
|
MK_CFLAGS = -D_UNICODE -DUNICODE -D_DEBUG
|
||||||
|
MK_CPPFLAGS = -D_UNICODE -DUNICODE -D_DEBUG
|
||||||
|
MK_RCFLAGS = -D_UNICODE -DUNICODE
|
||||||
|
|
||||||
|
# EOF
|
158
rosapps/templates/dialog/memdlg.c
Normal file
158
rosapps/templates/dialog/memdlg.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* ReactOS Standard Dialog Application Template
|
||||||
|
*
|
||||||
|
* memdlg.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern HINSTANCE hInst;
|
||||||
|
|
||||||
|
#define ID_HELP 150
|
||||||
|
#define ID_TEXT 200
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LRESULT CALLBACK DialogWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPWORD lpwAlign(LPWORD lpIn)
|
||||||
|
{
|
||||||
|
ULONG ul;
|
||||||
|
|
||||||
|
ul = (ULONG)lpIn;
|
||||||
|
ul += 3;
|
||||||
|
ul >>= 2;
|
||||||
|
ul <<= 2;
|
||||||
|
return (LPWORD)ul;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Create an in memory dialog resource and display.
|
||||||
|
// Note: this doesn't work
|
||||||
|
//
|
||||||
|
LRESULT CreateMemoryDialog(HINSTANCE hinst, HWND hwndOwner, LPSTR lpszMessage)
|
||||||
|
{
|
||||||
|
HGLOBAL hgbl;
|
||||||
|
LPDLGTEMPLATE lpdt;
|
||||||
|
LPDLGITEMTEMPLATE lpdit;
|
||||||
|
LPWORD lpw;
|
||||||
|
LPWSTR lpwsz;
|
||||||
|
LRESULT ret;
|
||||||
|
int nchar;
|
||||||
|
|
||||||
|
hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
|
||||||
|
if (!hgbl)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
|
||||||
|
|
||||||
|
// Define a dialog box.
|
||||||
|
lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION;
|
||||||
|
lpdt->cdit = 3; // number of controls
|
||||||
|
lpdt->x = 10; lpdt->y = 10;
|
||||||
|
lpdt->cx = 100; lpdt->cy = 100;
|
||||||
|
lpw = (LPWORD)(lpdt + 1);
|
||||||
|
*lpw++ = 0; // no menu
|
||||||
|
*lpw++ = 0; // predefined dialog box class (by default)
|
||||||
|
|
||||||
|
lpwsz = (LPWSTR)lpw;
|
||||||
|
nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "My Dialog", -1, lpwsz, 50);
|
||||||
|
lpw += nchar;
|
||||||
|
|
||||||
|
//-----------------------
|
||||||
|
// Define an OK button.
|
||||||
|
//-----------------------
|
||||||
|
lpw = lpwAlign(lpw); // align DLGITEMTEMPLATE on DWORD boundary
|
||||||
|
lpdit = (LPDLGITEMTEMPLATE)lpw;
|
||||||
|
lpdit->x = 10; lpdit->y = 70;
|
||||||
|
lpdit->cx = 80; lpdit->cy = 20;
|
||||||
|
lpdit->id = IDOK; // OK button identifier
|
||||||
|
lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
|
||||||
|
|
||||||
|
lpw = (LPWORD)(lpdit + 1);
|
||||||
|
*lpw++ = 0xFFFF;
|
||||||
|
*lpw++ = 0x0080; // button class
|
||||||
|
|
||||||
|
lpwsz = (LPWSTR)lpw;
|
||||||
|
nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "OK", -1, lpwsz, 50);
|
||||||
|
lpw += nchar;
|
||||||
|
lpw = lpwAlign(lpw); // align creation data on DWORD boundary
|
||||||
|
*lpw++ = 0; // no creation data
|
||||||
|
|
||||||
|
//-----------------------
|
||||||
|
// Define a Help button.
|
||||||
|
//-----------------------
|
||||||
|
lpw = lpwAlign(lpw); // align DLGITEMTEMPLATE on DWORD boundary
|
||||||
|
lpdit = (LPDLGITEMTEMPLATE)lpw;
|
||||||
|
lpdit->x = 55; lpdit->y = 10;
|
||||||
|
lpdit->cx = 40; lpdit->cy = 20;
|
||||||
|
lpdit->id = ID_HELP; // Help button identifier
|
||||||
|
lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
|
||||||
|
|
||||||
|
lpw = (LPWORD)(lpdit + 1);
|
||||||
|
*lpw++ = 0xFFFF;
|
||||||
|
*lpw++ = 0x0080; // button class atom
|
||||||
|
|
||||||
|
lpwsz = (LPWSTR)lpw;
|
||||||
|
nchar = 1 + MultiByteToWideChar(CP_ACP, 0, "Help", -1, lpwsz, 50);
|
||||||
|
lpw += nchar;
|
||||||
|
lpw = lpwAlign(lpw); // align creation data on DWORD boundary
|
||||||
|
*lpw++ = 0; // no creation data
|
||||||
|
|
||||||
|
//-----------------------
|
||||||
|
// Define a static text control.
|
||||||
|
//-----------------------
|
||||||
|
lpw = lpwAlign(lpw); // align DLGITEMTEMPLATE on DWORD boundary
|
||||||
|
lpdit = (LPDLGITEMTEMPLATE)lpw;
|
||||||
|
lpdit->x = 10; lpdit->y = 10;
|
||||||
|
lpdit->cx = 40; lpdit->cy = 20;
|
||||||
|
lpdit->id = ID_TEXT; // text identifier
|
||||||
|
lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
|
||||||
|
|
||||||
|
lpw = (LPWORD)(lpdit + 1);
|
||||||
|
*lpw++ = 0xFFFF;
|
||||||
|
*lpw++ = 0x0082; // static class
|
||||||
|
|
||||||
|
for (lpwsz = (LPWSTR)lpw;
|
||||||
|
*lpwsz++ = (WCHAR)*lpszMessage++;
|
||||||
|
);
|
||||||
|
lpw = (LPWORD)lpwsz;
|
||||||
|
lpw = lpwAlign(lpw); // align creation data on DWORD boundary
|
||||||
|
*lpw++ = 0; // no creation data
|
||||||
|
|
||||||
|
GlobalUnlock(hgbl);
|
||||||
|
ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE)hgbl, hwndOwner, (DLGPROC)DialogWndProc);
|
||||||
|
if (ret == 0) {
|
||||||
|
TRACE(_T("DialogBoxIndirect() failed due to invalid handle to parent window: 0x%08X"), hwndOwner);
|
||||||
|
} else if (ret == -1) {
|
||||||
|
DWORD error = GetLastError();
|
||||||
|
TRACE(_T("DialogBoxIndirect() failed, GetLastError returned 0x%08X"), error);
|
||||||
|
}
|
||||||
|
GlobalFree(hgbl);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
158
rosapps/templates/dialog/page1.c
Normal file
158
rosapps/templates/dialog/page1.c
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* ReactOS Standard Dialog Application Template
|
||||||
|
*
|
||||||
|
* page1.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define XBITMAP 80
|
||||||
|
#define YBITMAP 20
|
||||||
|
|
||||||
|
#define BUFFER_LEN MAX_PATH
|
||||||
|
|
||||||
|
extern HINSTANCE hInst;
|
||||||
|
|
||||||
|
HBITMAP hbmpPicture;
|
||||||
|
HBITMAP hbmpOld;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void AddItem(HWND hListBox, LPCTSTR lpstr, HBITMAP hbmp)
|
||||||
|
{
|
||||||
|
int nItem = SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)lpstr);
|
||||||
|
SendMessage(hListBox, LB_SETITEMDATA, nItem, (LPARAM)hbmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TCHAR* items[] = {
|
||||||
|
_T("services"),
|
||||||
|
_T("event log"),
|
||||||
|
_T("workstation"),
|
||||||
|
_T("server")
|
||||||
|
};
|
||||||
|
|
||||||
|
static void InitListCtrl(HWND hDlg)
|
||||||
|
{
|
||||||
|
TCHAR szBuffer[200];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
HWND hListBox = GetDlgItem(hDlg, IDC_LIST1);
|
||||||
|
|
||||||
|
_tcscpy(szBuffer, _T("foobar item"));
|
||||||
|
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)szBuffer);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(items)/sizeof(items[0]); i++) {
|
||||||
|
_tcscpy(szBuffer, items[i]);
|
||||||
|
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)szBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFocus(hListBox);
|
||||||
|
SendMessage(hListBox, LB_SETCURSEL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnDrawItem(HWND hWnd, LPARAM lParam)
|
||||||
|
{
|
||||||
|
// int nItem;
|
||||||
|
TCHAR tchBuffer[BUFFER_LEN];
|
||||||
|
// HBITMAP hbmp;
|
||||||
|
TEXTMETRIC tm;
|
||||||
|
int y;
|
||||||
|
HDC hdcMem;
|
||||||
|
LPDRAWITEMSTRUCT lpdis;
|
||||||
|
RECT rcBitmap;
|
||||||
|
|
||||||
|
lpdis = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
// If there are no list box items, skip this message.
|
||||||
|
if (lpdis->itemID != -1) {
|
||||||
|
// Draw the bitmap and text for the list box item. Draw a rectangle around the bitmap if it is selected.
|
||||||
|
switch (lpdis->itemAction) {
|
||||||
|
case ODA_SELECT:
|
||||||
|
case ODA_DRAWENTIRE:
|
||||||
|
// Display the bitmap associated with the item.
|
||||||
|
hbmpPicture = (HBITMAP)SendMessage(lpdis->hwndItem, LB_GETITEMDATA, lpdis->itemID, (LPARAM)0);
|
||||||
|
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
||||||
|
hbmpOld = SelectObject(hdcMem, hbmpPicture);
|
||||||
|
BitBlt(lpdis->hDC,
|
||||||
|
lpdis->rcItem.left, lpdis->rcItem.top,
|
||||||
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
||||||
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
||||||
|
hdcMem, 0, 0, SRCCOPY);
|
||||||
|
// Display the text associated with the item.
|
||||||
|
SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)tchBuffer);
|
||||||
|
GetTextMetrics(lpdis->hDC, &tm);
|
||||||
|
y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
|
||||||
|
TextOut(lpdis->hDC, XBITMAP + 6, y, tchBuffer, _tcslen(tchBuffer));
|
||||||
|
SelectObject(hdcMem, hbmpOld);
|
||||||
|
DeleteDC(hdcMem);
|
||||||
|
// Is the item selected?
|
||||||
|
if (lpdis->itemState & ODS_SELECTED) {
|
||||||
|
// Set RECT coordinates to surround only the bitmap.
|
||||||
|
rcBitmap.left = lpdis->rcItem.left;
|
||||||
|
rcBitmap.top = lpdis->rcItem.top;
|
||||||
|
rcBitmap.right = lpdis->rcItem.left + XBITMAP;
|
||||||
|
rcBitmap.bottom = lpdis->rcItem.top + YBITMAP;
|
||||||
|
// Draw a rectangle around bitmap to indicate the selection.
|
||||||
|
DrawFocusRect(lpdis->hDC, &rcBitmap);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ODA_FOCUS:
|
||||||
|
// Do not process focus changes. The focus caret (outline rectangle)
|
||||||
|
// indicates the selection. The IDOK button indicates the final selection.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK PageWndProc1(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
LPMEASUREITEMSTRUCT lpmis;
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
InitListCtrl(hDlg);
|
||||||
|
return TRUE;
|
||||||
|
case WM_MEASUREITEM:
|
||||||
|
lpmis = (LPMEASUREITEMSTRUCT)lParam;
|
||||||
|
// Set the height of the list box items.
|
||||||
|
lpmis->itemHeight = 20;
|
||||||
|
return TRUE;
|
||||||
|
case WM_DRAWITEM:
|
||||||
|
OnDrawItem(hDlg, lParam);
|
||||||
|
return TRUE;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam)) {
|
||||||
|
case IDOK:
|
||||||
|
case IDCANCEL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
55
rosapps/templates/dialog/page2.c
Normal file
55
rosapps/templates/dialog/page2.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* ReactOS Standard Dialog Application Template
|
||||||
|
*
|
||||||
|
* page2.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern HINSTANCE hInst;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LRESULT CALLBACK PageWndProc2(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
return TRUE;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam)) {
|
||||||
|
case IDOK:
|
||||||
|
case IDCANCEL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
55
rosapps/templates/dialog/page3.c
Normal file
55
rosapps/templates/dialog/page3.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* ReactOS Standard Dialog Application Template
|
||||||
|
*
|
||||||
|
* page3.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern HINSTANCE hInst;
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LRESULT CALLBACK PageWndProc3(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
return TRUE;
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam)) {
|
||||||
|
case IDOK:
|
||||||
|
case IDCANCEL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
14
rosapps/templates/dialog/resource.h
Normal file
14
rosapps/templates/dialog/resource.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// resource.h - Used by TabTest.rc
|
||||||
|
//
|
||||||
|
#define IDD_TABBED_DIALOG 101
|
||||||
|
#define IDR_ACCELERATOR 103
|
||||||
|
#define IDD_PAGE1 104
|
||||||
|
#define IDD_PAGE2 105
|
||||||
|
#define IDD_PAGE3 106
|
||||||
|
#define IDC_TAB 1000
|
||||||
|
#define IDC_BUTTON1 1001
|
||||||
|
#define IDC_CHECK1 1002
|
||||||
|
#define IDC_SLIDER1 1003
|
||||||
|
#define IDC_LIST1 1004
|
||||||
|
#define IDC_STATIC -1
|
53
rosapps/templates/dialog/trace.c
Normal file
53
rosapps/templates/dialog/trace.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Diagnostic Trace
|
||||||
|
//
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#undef THIS_FILE
|
||||||
|
static char THIS_FILE[] = __FILE__;
|
||||||
|
|
||||||
|
void _DebugBreak(void)
|
||||||
|
{
|
||||||
|
DebugBreak();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace(TCHAR* lpszFormat, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int nBuf;
|
||||||
|
TCHAR szBuffer[512];
|
||||||
|
|
||||||
|
va_start(args, lpszFormat);
|
||||||
|
nBuf = _vsntprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), lpszFormat, args);
|
||||||
|
OutputDebugString(szBuffer);
|
||||||
|
// was there an error? was the expanded string too long?
|
||||||
|
//ASSERT(nBuf >= 0);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assert(void* assert, TCHAR* file, int line, void* msg)
|
||||||
|
{
|
||||||
|
if (msg == NULL) {
|
||||||
|
printf("ASSERT -- %s occured on line %u of file %s.\n",
|
||||||
|
assert, line, file);
|
||||||
|
} else {
|
||||||
|
printf("ASSERT -- %s occured on line %u of file %s: Message = %s.\n",
|
||||||
|
assert, line, file, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
void Trace(TCHAR* lpszFormat, ...) { };
|
||||||
|
void Assert(void* assert, TCHAR* file, int line, void* msg) { };
|
||||||
|
|
||||||
|
#endif //_DEBUG
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
61
rosapps/templates/dialog/trace.h
Normal file
61
rosapps/templates/dialog/trace.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Diagnostic Trace
|
||||||
|
//
|
||||||
|
#ifndef __TRACE_H__
|
||||||
|
#define __TRACE_H__
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
#ifdef _X86_
|
||||||
|
#define BreakPoint() _asm { int 3h }
|
||||||
|
#else
|
||||||
|
#define BreakPoint() _DebugBreak()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ASSERT
|
||||||
|
#define ASSERT(exp) \
|
||||||
|
{ \
|
||||||
|
if (!(exp)) { \
|
||||||
|
Assert(#exp, __FILE__, __LINE__, NULL); \
|
||||||
|
BreakPoint(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define ASSERTMSG(exp, msg) \
|
||||||
|
{ \
|
||||||
|
if (!(exp)) { \
|
||||||
|
Assert(#exp, __FILE__, __LINE__, msg); \
|
||||||
|
BreakPoint(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// MACRO: TRACE()
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#define TRACE Trace
|
||||||
|
|
||||||
|
|
||||||
|
#else // _DEBUG
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Define away MACRO's ASSERT() and TRACE() in non debug builds
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifndef ASSERT
|
||||||
|
#define ASSERT(exp)
|
||||||
|
#define ASSERTMSG(exp, msg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TRACE 0 ? (void)0 : Trace
|
||||||
|
|
||||||
|
#endif // !_DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
void Assert(void* assert, TCHAR* file, int line, void* msg);
|
||||||
|
void Trace(TCHAR* lpszFormat, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __TRACE_H__
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
Loading…
Reference in a new issue