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

// Introduction to Windows Programming

// Dialog.c

// created:   20/02/96   Rainer Döbele

// modified:

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

#include <windows.h>     // we always need to include the windows header file

#include <string.h>

#include "dialog.h"      // this is our own header file used e.g. to define ressource IDs

// Global variables

// Note:  use globals only for constants which are valid thoughout

//        the whole time of program execution

HINSTANCE hInstance;     // Global Handle to Program Instance

// Prototypes of exported functions called by Windows

BOOL FAR PASCAL MainDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam);

BOOL FAR PASCAL AboutDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam);

// Prototypes of internally

void SortList(HWND hDlg,int idList,BOOL bCaseSensitive,BOOL bDescendingOrder);

// define the maximum length of a name

#define MAXNAMELEN  50

// Macros to overcome differences between Win16 and Win32

#ifdef WIN32

  // Win32

  #define CTLID   LOWORD(wParam)      // Control ID for WM_COMMAND

  #define CTLMSG  HIWORD(wParam)      // Notification Message of Control

  #define HCTL   (HWND)lParam         // window handle of control

#else

  // Win16

  #define CTLID   wParam              // Control ID for WM_COMMAND

  #define CTLMSG  HIWORD(lParam)      // Notification Message of Control

  #define HCTL   (HWND)LOWORD(lParam) // window handle of control

#endif

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

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)

{

  // Store the instance handle in case we need it later on

  hInstance=hInst;

  // Call our dialog

  DialogBox(hInstance,MAKEINTRESOURCE(DLG_MAIN),NULL,MainDlgProc);

  // Program was terminated

  return TRUE;

}

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

BOOL FAR PASCAL MainDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)

{

  switch (msg)

    {

       case WM_INITDIALOG:

            // Disable all buttons that cannot be pushed at start

            EnableWindow(GetDlgItem(hDlg,IDC_ADDNAME),FALSE);

            EnableWindow(GetDlgItem(hDlg,IDC_SORTLIST),FALSE);

            // Set Defaults for Option

            CheckRadioButton(hDlg,IDC_ASCENDING,IDC_DESCENDING,IDC_ASCENDING);

            CheckDlgButton(hDlg,IDC_CASEINSENSITIVE,TRUE);

            // Set the maximum name length

            SendDlgItemMessage(hDlg,IDC_NAME,EM_LIMITTEXT,MAXNAMELEN,0L);

            break;

       case WM_COMMAND:

            // We received a notification message from a control

            switch(CTLID)

              {

                case IDC_NAME: // Notification message from edit control

                     if (CTLMSG==EN_UPDATE)

                       { // something changed in the edit field

                         // Check whether there is text in the name-field

                         int len=SendDlgItemMessage(hDlg,IDC_NAME,EM_LINELENGTH,0,0L);

                         EnableWindow(GetDlgItem(hDlg,IDC_ADDNAME),len);

                       }

                     break;

                case IDC_NAMELIST: // Notification message from list control

                     if (CTLMSG==LBN_DBLCLK)

                       { // User double-clicked a list item

                         // find out which item

                         int i=SendDlgItemMessage(hDlg,IDC_NAMELIST,LB_GETCURSEL,0,0L);

                         if (i>=0 && MessageBox(hDlg,"Do you want to delete this item","Confirm",MB_ICONQUESTION|MB_YESNO)==IDYES)

                           { // Delete the item

                             SendDlgItemMessage(hDlg,IDC_NAMELIST,LB_DELETESTRING,i,0L);

                           }

                       }

                     break;

                case IDC_ADDNAME:  // Button Add name was clicked

                     { char szName[MAXNAMELEN];

                       // Get the name from the edit control

                       GetDlgItemText(hDlg,IDC_NAME,szName,MAXNAMELEN);

                       // and add it to the list

                       SendDlgItemMessage(hDlg,IDC_NAMELIST,LB_ADDSTRING,0,(LPARAM)(LPSTR)szName);

                       // Delete the name in the deit control

                       SetDlgItemText(hDlg,IDC_NAME,NULL);

                       SetFocus(GetDlgItem(hDlg,IDC_NAME));

                       // Enable the sort button

                       EnableWindow(GetDlgItem(hDlg,IDC_SORTLIST),TRUE);

                     }

                     break;

                case IDC_SORTLIST: // Button Sort list was clicked

                     { // Get the sort options

                       BOOL bCaseInsensitive=IsDlgButtonChecked(hDlg,IDC_CASEINSENSITIVE);

                       BOOL bDescendingOrder=IsDlgButtonChecked(hDlg,IDC_DESCENDING);

                       // Now sort it

                       SortList(hDlg,IDC_NAMELIST,bCaseInsensitive,bDescendingOrder);

                     }

                     break;

                // Menu Commands

                case IDM_QUIT:

                     // user selected Quit from the menu

                     EndDialog(hDlg,TRUE);

                     break;

                case IDM_ABOUT:

                     // Call about dialog

                     DialogBox(hInstance,MAKEINTRESOURCE(DLG_ABOUT),hDlg,AboutDlgProc);

                     break;

                // Keyboard commands (only Return, Esc and F1 are forwarded)

                case IDCANCEL:

                     { int answer;

                       // User closed the window or pressed escape

                       answer=MessageBox(hDlg,"Do you really want to quit?","Confirm",MB_ICONQUESTION|MB_YESNO);

                       if (answer==IDYES) EndDialog(hDlg,FALSE);

                     }

                     break;

              }

            break;

       #ifdef WIN32

       // Set the background color for WIN32

       case WM_CTLCOLORDLG:

       case WM_CTLCOLORSTATIC:

       case WM_CTLCOLORBTN:

            SetBkColor((HDC)wParam,RGB(192,192,192));

            return (BOOL)GetStockObject(LTGRAY_BRUSH);

       #else

       // Set the background color for WIN16

       case WM_CTLCOLOR:

            switch(HIWORD(lParam))

             {

               case CTLCOLOR_DLG:

               case CTLCOLOR_STATIC:

               case CTLCOLOR_BTN:

                    SetBkColor((HDC)wParam,RGB(192,192,192));

                    return GetStockObject(LTGRAY_BRUSH);

             }

            return FALSE; // use the defaults

       #endif

       case WM_DESTROY:

            // Clean up if neccessary

            // e.g. free allocated memory

            break;

       default:

            // we did not processes the messages

            // so let windows do it

            return FALSE;

    }

  // we processed the dialogue messages

  return TRUE;

}

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

void SortList(HWND hDlg,int idList,BOOL bCaseInsensitive,BOOL bDescendingOrder)

{ int  nItems,i,j;

  BOOL bSwap;

  char buffer1[MAXNAMELEN],buffer2[MAXNAMELEN];

  // Get the total number of list items

  nItems=SendDlgItemMessage(hDlg,idList,LB_GETCOUNT,0,0L);

  // Use Bubble Sort to sort the list

  for (i=nItems;i>0;i--)

   {

    // Get the text of the first item in the list

    SendDlgItemMessage(hDlg,idList,LB_GETTEXT,0,(LPARAM)(LPSTR)buffer1);

    for (j=1;j<i;j++)

       { // Get the text of the next item in the list

         SendDlgItemMessage(hDlg,idList,LB_GETTEXT,j,(LPARAM)(LPSTR)buffer2);

         // compare the two strings

         if (bCaseInsensitive) bSwap=(lstrcmpi(buffer1,buffer2)>0);

                          else bSwap=(strcmp(buffer1,buffer2)>0);

         if (bDescendingOrder) bSwap=!bSwap;

         // Swap the items if necessary

         if (bSwap)

           { // since there is no LB_SETTEXT we delete the item first and then

             // insert it again before the previous item

             SendDlgItemMessage(hDlg,idList,LB_DELETESTRING,j,0L);

             SendDlgItemMessage(hDlg,idList,LB_INSERTSTRING,j-1,(LPARAM)(LPSTR)buffer2);

           }

         else lstrcpy(buffer1,buffer2);

       }

   }

}

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

BOOL FAR PASCAL AboutDlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)

{ // this is the dialogue procedure for the About dialogue

  switch (msg)

    {

       case WM_INITDIALOG:

            // Add code here to initialize Controls

            break;

       case WM_COMMAND:

            // We received a notification message from a control

            switch(CTLID)

              {

                case IDOK:

                case IDCANCEL:

                     EndDialog(hDlg,TRUE);

                     break;

              }

            break;

       default:

            // we did not processes the messages

            // so let windows do it

            return FALSE;

    }

  // we processed the dialogue messages

  return TRUE;

}

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


Back to tutorial