Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Mini-Calc: Restore-Position

Part of WindowsGuiCategory

Description

Simple windows app that stores it upper-left coordinates in registry so that it can remember where it was when the app was closed.

Example

/*
 *  Copyright (C) 2004 by Digital Mars, www.digitalmars.com
 *  Written by Lynn Allan
 *  This software is provided 'as-is'. Released to public domain.
 *
 * Compile with:
 *  dmd MiniCalc.d gdi32.lib advapi32.lib MiniCalc.def
 *
 * You'll also need a .def file with at least the following in it:
 *  EXETYPE NT
 *  SUBSYSTEM WINDOWS
 *
 * Current as of dmd ver 0.102. In the basic dmd distribution, there
 *   are missing extern definitions for registry and windowplacement
 *   constants and structures. For now, these have been provided. There
 *   are auxillary files registry.d and win32.commctrl.d that will 
 *   probably eventually be included with the standard phobos distribution.
 */

import std.string;
import std.c.windows.windows;

private enum {
IDC_BTN_PLUS = 103,
IDC_BTN_MINUS,
IDC_EDIT_FIRST_NUMBER,
IDC_EDIT_SECOND_NUMBER,
IDC_EDIT_RESULT_NUMBER
}

private HINSTANCE ghInstance;
private HWND      ghPlusBtn;
private HWND      ghMinusBtn;
private HWND      ghFirstNumberEdit;
private HWND      ghSecondNumberEdit;
private HWND      ghResultNumberEdit;
private HWND      ghWndMain;

private int gDlgTop;
private int gDlgLeft;

void CreateControls()
{
  HWND hChapSelectorTree;
  
  ghPlusBtn = CreateWindowA("BUTTON", "Plus", 
                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                 5, 5, 53, 25, ghWndMain, cast(HMENU) IDC_BTN_PLUS, 
                 ghInstance, null);

  ghMinusBtn = CreateWindowA("BUTTON", "Minus", 
                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
                 60, 5, 53, 25, ghWndMain, 
                 cast(HMENU) IDC_BTN_MINUS, 
                 ghInstance, null);

  ghFirstNumberEdit = CreateWindowA("EDIT", toString(gDlgLeft), 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 32, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_FIRST_NUMBER, ghInstance, null);

  ghSecondNumberEdit = CreateWindowA("EDIT", toString(gDlgTop), 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 60, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_SECOND_NUMBER, ghInstance, null);
  
  ghResultNumberEdit = CreateWindowA("EDIT", "", 
                 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT,
                 5, 87, 110, 25, ghWndMain, 
                 cast(HMENU) IDC_EDIT_RESULT_NUMBER, 
                 ghInstance, null);
}

void DoMessagePump()
{
  MSG msg;
  while (GetMessageA(&msg, cast(HWND) null, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessageA(&msg);
  }
}

void CreateMainWindow()
{
  HWND hWnd;
  hWnd = CreateWindowA("DWndClass", 
               "MiniCalc", 
               WS_THICKFRAME | WS_MAXIMIZEBOX 
               | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
               gDlgLeft, gDlgTop,
               125, 150,       // width & height
               HWND_DESKTOP,
               cast(HMENU) null, ghInstance, null);
  assert(hWnd);
  ghWndMain = hWnd;

}

void InitApplication()
{
  WNDCLASS wc;
  wc.lpszClassName = "DWndClass";
  wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = &WindowProc;
  wc.hInstance = ghInstance;
  wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
  wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
  wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
  wc.lpszMenuName = null;
  wc.cbClsExtra = wc.cbWndExtra = 0;

  assert(RegisterClassA(&wc));
}

void InitInstance()
{
  ghInstance = GetModuleHandleA(null);
  InitApplication();

  InitRegistry();

  CreateMainWindow();

  CreateControls();
}

extern (Windows)   // Not defined in windows.d ... use Core32
{
LONG RegQueryValueExA(HKEY hkey, 
                      LPCTSTR keyName, 
                      LPDWORD reservedNull,
                      LPDWORD type, 
                      void*   data,
                      LPDWORD len);

struct WINDOWPLACEMENT {
    UINT  length;
    UINT  flags;
    UINT  showCmd;
    POINT ptMinPosition;
    POINT ptMaxPosition;
    RECT  rcNormalPosition;
}
BOOL GetWindowPlacement(HWND hWnd,WINDOWPLACEMENT *lpwndpl);
}

private void InitRegistry()
{
  HKEY hkey;
  LONG result;
  DWORD dwType;
  const int BUF_SZ = 4;
  DWORD dwLen = BUF_SZ;
  DWORD displosition;

  result = RegCreateKeyExA(HKEY_CURRENT_USER, 
                           "Software\\dSource\\MiniCalc\\Settings", 
                           cast(uint)null,
                           null,
                           REG_OPTION_NON_VOLATILE,
                           KEY_ALL_ACCESS,
                           null,
                           &hkey,
                           &displosition);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  result = RegCloseKey(hkey);
  assert(result == ERROR_SUCCESS);

  result = RegOpenKeyA(HKEY_CURRENT_USER, 
                       "Software\\dSource\\MiniCalc\\Settings", &hkey);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  try {
    dwLen = 4;
    result = RegQueryValueExA(hkey, 
                              cast(char*)"DlgTop", 
                              null, 
                              &dwType, 
                              cast(void*)&gDlgTop, 
                              &dwLen); 
    assert(result == ERROR_SUCCESS);

    result = RegQueryValueExA(hkey, 
                              cast(char*)"DlgLeft", 
                              null, 
                              &dwType, 
                              cast(void*)&gDlgLeft, 
                              &dwLen); 
    assert(result == ERROR_SUCCESS);
  }
  catch(Object o) {
    gDlgLeft = 400;
    gDlgTop  = 50;
  }
  result = RegCloseKey(hkey);
  assert(result == ERROR_SUCCESS);
}

private void SaveRegistrySettings()
{
  DWORD dwLen;
  HKEY  hkey;
  LONG  result;

  result = RegOpenKeyA(HKEY_CURRENT_USER, 
                       "Software\\dSource\\MiniCalc\\Settings", 
                       &hkey);
  assert(result == std.c.windows.windows.ERROR_SUCCESS);

  dwLen = 4;
  result = RegSetValueExA(hkey, 
                          cast(char*)"DlgTop", 
                          0, 
                          REG_DWORD, 
                          cast(BYTE*)&gDlgTop, 
                          dwLen);
  assert(result == ERROR_SUCCESS);

  result = RegSetValueExA(hkey, 
                          cast(char*)"DlgLeft", 
                          0, 
                          REG_DWORD, 
                          cast(BYTE*)&gDlgLeft, 
                          dwLen);
  assert(result == ERROR_SUCCESS);

  result = RegCloseKey(hkey);
  assert(result == ERROR_SUCCESS);
}

private void GetCurrentMainWindowPosition()
in { assert(ghWndMain != null); }
body {
  WINDOWPLACEMENT windowPlacement;
  int flag  = GetWindowPlacement(ghWndMain, &windowPlacement);
  assert (flag != 0);

  debug { int _dbg_left = windowPlacement.rcNormalPosition.left; }
  gDlgLeft = windowPlacement.rcNormalPosition.left;
  gDlgTop  = windowPlacement.rcNormalPosition.top;
}

/**********************************************************/

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();

extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
            LPSTR lpCmdLine, int nCmdShow)
{
  int result = 1;

  gc_init();      // initialize garbage collector
  _minit();     // initialize module constructor table

  try {
    _moduleCtor();    // call module constructors
    _moduleUnitTests(); // run unit tests (optional)

    InitInstance();
    DoMessagePump();
  }
  catch (Object o) {    // catch any uncaught exceptions
    MessageBoxA(null, cast(char *)o.toString(), "Error",
                MB_OK | MB_ICONEXCLAMATION);
    result = 0;   // failed
  }
  gc_term();      // run finalizers; terminate garbage collector
  return result;
}

extern(Windows)
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
  char[8] firstNumber;
  char[8] secondNumber;
  int count;
  long num1;
  long num2;

  switch (uMsg) {
    case WM_COMMAND: {
      switch (LOWORD(wParam)) {
        case IDC_BTN_PLUS:
          if (HIWORD(wParam) == BN_CLICKED) {
            count = SendMessageA(ghFirstNumberEdit, WM_GETTEXT, 
                                 6, cast(int)cast(char*)firstNumber);
            count = SendMessageA(ghSecondNumberEdit, WM_GETTEXT, 
                                 6, cast(int)cast(char*)secondNumber);
            num1 = atoi(cast(char[])firstNumber);
            num2 = atoi(cast(char[])secondNumber);
            SendMessageA(ghResultNumberEdit, WM_SETTEXT, 
                         8, cast(int)cast(char*)toString(num1 + num2));
          }
          break;

        case IDC_BTN_MINUS:
          if (HIWORD(wParam) == BN_CLICKED) {
            count = SendMessageA(ghFirstNumberEdit, 
                                 WM_GETTEXT, 8, 
                                 cast(int)cast(char*)firstNumber);
            count = SendMessageA(ghSecondNumberEdit, 
                                 WM_GETTEXT, 8, 
                                 cast(int)cast(char*)secondNumber);
            num1 = atoi(cast(char[])firstNumber);
            num2 = atoi(cast(char[])secondNumber);
            SendMessageA(ghResultNumberEdit, 
                         WM_SETTEXT, 8, 
                         cast(int)cast(char*)toString(num1 - num2));
          }
          break;
        case IDC_EDIT_FIRST_NUMBER:
          break;
        case IDC_EDIT_SECOND_NUMBER:
          break;
        case IDC_EDIT_RESULT_NUMBER:
          break;
      }
      break;
    }
    case WM_DESTROY:
      GetCurrentMainWindowPosition();
      SaveRegistrySettings();
      PostQuitMessage(0);
      break;

    case WM_NOTIFY:
      break;

    default:
      break;
  }
  return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}

Source

Posted by Lynn
Date/Time Thu Oct 14, 2004 10:35 am