Skip to content

Commit

Permalink
Prepare for version 1.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinPayne committed Nov 10, 2017
0 parents commit 4b96de4
Show file tree
Hide file tree
Showing 14 changed files with 647 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Ignore compiler output
*.bsc
*.crf
*.bnd
*.exe
*.lk1
*.map
*.obj
*.pdb
*.res
*.sbr
*.sym

# Ignore Visual Studio files
*.aps
*.vcw
*.wsp
39 changes: 39 additions & 0 deletions AboutDlg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "AboutDlg.h"
#include "Globals.h"
#include "Resource.h"

/* Dialog procedure for our "about" dialog */
BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
{
WORD id = wParam;

switch (id)
{
case IDOK:
case IDCANCEL:
{
EndDialog(hwndDlg, id);
return TRUE;
}
}
break;
}

case WM_INITDIALOG:
{
return TRUE;
}
}

return FALSE;
}

/* Show our "about" dialog */
void ShowAboutDialog(HWND owner)
{
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_ABOUTDIALOG), owner, &AboutDialogProc);
}
12 changes: 12 additions & 0 deletions AboutDlg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef ABOUTDLG_H
#define ABOUTDLG_H

#include <windows.h>

/* Dialog procedure for our "about" dialog */
BOOL CALLBACK __export AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

/* Show our "about" dialog */
void ShowAboutDialog(HWND owner);

#endif
Binary file added App.ico
Binary file not shown.
9 changes: 9 additions & 0 deletions Globals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef GLOBALS_H
#define GLOBALS_H

#include <windows.h>

/* Global instance handle */
extern HINSTANCE g_hInstance;

#endif
24 changes: 24 additions & 0 deletions License.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org>
117 changes: 117 additions & 0 deletions MainWnd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include "AboutDlg.h"
#include "Globals.h"
#include "MainWnd.h"
#include "Resource.h"

/* Main window class and title */
static const char MainWndClass[] = "Win16 Dialog Application";

/* Window procedure for our main window */
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
{
WORD id = wParam;

switch (id)
{
case ID_HELP_ABOUT:
{
ShowAboutDialog(hWnd);
return 0;
}

case IDOK:
case IDCANCEL:
{
DestroyWindow(hWnd);
return 0;
}
}
break;
}

/* Item from system menu has been invoked */
case WM_SYSCOMMAND:
{
WORD id = wParam;

switch (id)
{
/* Show "about" dialog on about system menu item */
case ID_HELP_ABOUT:
{
ShowAboutDialog(hWnd);
return 0;
}
}
break;
}

case WM_CREATE:
{
HWND dummyWnd;
RECT rect;

/* We want the OS to position the window, but this can't be done with windows created using CreateDialog.
* Therefore we create a temporary dummy window to see where it would have been positioned, and then move the
* dialog to that position. */
dummyWnd = CreateWindowEx(0, "STATIC", "STATIC", 0, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, g_hInstance,
NULL);
GetWindowRect(dummyWnd, &rect);
DestroyWindow(dummyWnd);

/* Move the dialog to where the dummy window was positioned */
SetWindowPos(hWnd, 0, rect.left, rect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

return 0;
}

case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}

return DefWindowProc(hWnd, msg, wParam, lParam);
}

/* Register a class for our main window */
BOOL RegisterMainWindowClass()
{
WNDCLASS wc;

/* Class for our main window */
wc.style = 0;
wc.lpfnWndProc = &MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = g_hInstance;
wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_APPICON));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = MainWndClass;

return (RegisterClass(&wc)) ? TRUE : FALSE;
}

/* Create an instance of our main window */
HWND CreateMainWindow()
{
/* Create instance of main window */
HWND hWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, NULL);

if (hWnd)
{
/* Add "about" to the system menu */
HMENU hSysMenu = GetSystemMenu(hWnd, FALSE);
InsertMenu(hSysMenu, 5, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
InsertMenu(hSysMenu, 6, MF_BYPOSITION, ID_HELP_ABOUT, "About");
}

return hWnd;
}
15 changes: 15 additions & 0 deletions MainWnd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef MAINWND_H
#define MAINWND_H

#include <windows.h>

/* Window procedure for our main window */
LRESULT CALLBACK __export MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

/* Register a class for our main window */
BOOL RegisterMainWindowClass(void);

/* Create an instance of our main window */
HWND CreateMainWindow(void);

#endif
90 changes: 90 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Win16 Dialog Application

## Table of Contents

- [Introduction](#introduction)
- [Building the Application](#building-the-application)
- [Smart Callbacks](#smart-callbacks)
- [Terms of Use](#terms-of-use)
- [Problems?](#problems)
- [Changelog](#changelog)

## Introduction

This application is an example Win16 dialog application. It uses a dialog resource and Windows dialog box functions for
creating the dialog, meaning it can be edited using App Studio in Visual C++ (or the equivalent in other IDEs) rather
than having to manually create controls at runtime.

The following changes from a standard Windows application are required for this to happen:

- The dialog being used for the main window must have a class name associated with it. This is done by setting the
"Registered Class" property on the dialog.
- The Window class for the main window must have the "cbWndExtra" field set to "DLGWINDOWEXTRA", and the "lpszClassName"
must match the class name you gave to the dialog resource. All other properties (e.g. the window procedure and icons)
are set the same as you normally would for a Windows application.
- The dialog window is created with "CreateDialog()" rather than "CreateWindow()". The "lpTemplate" parameter should be
set to the resource ID of the dialog (not the class name of the dialog!), and the "lpDialogFunc" parameter should be
set to NULL.
- The application's message pump should call "IsDialogMessage()" on each message it gets. This is optional, but doing so
means that the dialog behaves like a dialog, e.g. pressing the tab key moves focus to the next dialog control.
- The "WM_CREATE" message handler includes some code to reposition the dialog before it is displayed. This is also
optional, but if this isn't done then the dialog will always display in the centre of the main display. If two
instances of the application are launched, the second instance could hide the first one.

Other than that, the application code is the same as that for a standard Windows application.

The application can be built using Visual C++ 1.5x. You can
[download Visual C++ 1.52](https://my.visualstudio.com/Downloads?pid=140) if you have a Visual Studio Subscription. If
you don't have a subscription, you can download the
[Windows Server 2003 DDK](http://download.microsoft.com/download/9/0/f/90f019ac-8243-48d3-91cf-81fc4093ecfd/1830_usa_ddk.iso)
which contains the 16 bit command line tools (most of which are from Visual C++ 1.52). The 16 bit binaries can be found
in "bin\bin16" of the installed DDK, include files in "inc\inc16", and lib files in "lib\lib16". A number of the
binaries come in two versions, one with and one without a "16" suffix, e.g. "cl.exe" and "cl16.exe". Despite the
different filenames, the file contents are identical.

With a few small changes to the Makefile, the application will build with Microsoft C / C++ 7.0 and the Windows 3.1 SDK.
It won't build with the Windows 3.0 SDK because the headers don't define some of the required types, and it does not
have the "ver.h" header which is required for the version information resource.

## Building the Application

To build the application with the Microsoft Visual C++ 1.5x GUI, go to "project", "open", then open "Win16Dlg.mak". To
choose a debug or release build, go to "options" then "project". The project can be built using the "build" or "rebuild"
toolbar items, or via the "project" menu.

To build the application from the command line with Visual C++ 1.5x, launch a command prompt, run the "MSVCVARS.BAT"
file which can be found in the Visual C++ "bin" directory, and then navigate to the directory containing the Makefile.
Run "nmake /f Win16Dlg.mak" to build. This also works with the Windows Server 2003 DDK, but instead of running
"MSVCVARS.BAT", you will need to add the "bin16" directory to your "%PATH%" environment variable, "inc16" to
"%INCLUDE%", and "lib16" to "%LIB%".

## Smart Callbacks

This application makes use of so-called "smart callbacks". This means the data segment register is loaded from the
stack segment register on entry to any callback function which is called by Windows. The result of this is that it is
not necessary to list the callback functions in the application's module definition file, and it is not necessary to use
"MakeProcInstance" to create a thunk when (e.g.) displaying a dialog box. In Visual C++ this is achieved by marking
callback functions with the "__export" modifier, and using the "/GA /GEs /GEm" compiler options (optimise far function
epilogs, load DS from SS, and increment BP on entry to the callback--required only for real mode stack walking support).
You can also use the "/GEf" option, which means all far functions are given the code to load DS from SS regardless of
whether they are callback functions. This is slightly less efficient, but does mean that callback functions don't
require the "__export" modifier.

Refer to the [Windows 1 Application](https://github.com/TransmissionZero/Windows-1-Example-Application) for an example
application which uses "MakeProcInstance" rather than smart callbacks.

## Terms of Use

Refer to "License.txt" for terms of use.

## Problems?

If you have any problems or questions, please ensure you have read this readme. If you are still having trouble, you can
[get in contact](http://www.transmissionzero.co.uk/contact/).

## Changelog
1. 2017-11-10: Version 1.0
- Initial release.

Transmission Zero
2017-11-10
22 changes: 22 additions & 0 deletions Resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//{{NO_DEPENDENCIES}}
// App Studio generated include file.
// Used by RESOURCE.RC
//
#define IDI_APPICON 100
#define IDR_ACCELERATOR 102
#define IDD_MAINDIALOG 103
#define IDD_ABOUTDIALOG 104
#define ID_HELP_ABOUT 200
#define IDC_STATIC -1

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 101
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Loading

0 comments on commit 4b96de4

Please sign in to comment.