home *** CD-ROM | disk | FTP | other *** search
- _SUBCLASSING APPLICATIONS_
- by Mike Klein
-
- [LISTING ONE]
-
- # Standard Windows make file. The utility MAKE.EXE compares the
- # creation date of the file to the left of the colon with the file(s)
- # to the right of the colon. If the file(s) on the right are newer
- # then the file on the left, Make will execute all of the command lines
- # following this line that are indented by at least one tab or space.
- # Any valid MS-DOS command line may be used.
-
- # This line allows NMAKE to work as well
- all: progedit.exe
-
- # Update the resource if necessary
- progedit.res: progedit.rc progedit.h progedit.ico
- rc -r progedit.rc
-
- # Update the object file if necessary
- progedit.obj: progedit.c progedit.h
- cl -W4 -c -AS -Gsw -Oad -Zp progedit.c
-
- # Update the executable file if necessary, and if so, add the resource back in.
- progedit.exe: progedit.obj progedit.def
- link /NOD progedit,,, libw slibcew, progedit.def
- rc progedit.res
-
- # If the .res file is new and the .exe file is not, update the resource.
- # Note that the .rc file can be updated without having to either
- # compile or link the file.
- progedit.exe: progedit.res
- rc progedit.res
-
-
-
-
- [LISITNG TWO]
-
- #define IDC_TABAMT 100
-
- int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
-
- LONG FAR PASCAL MyMainWndProc(HWND, unsigned, WORD, LONG);
- BOOL FAR PASCAL TabAmount(HWND, unsigned, WORD, LONG);
-
-
-
-
- [LISTING THREE]
-
- ; module-definition file for Progeddit -- used by LINK.EXE
-
- NAME PROGEDIT ; application's module name
- DESCRIPTION 'Progedit - Programming Editor'
- EXETYPE WINDOWS ; required for all Windows applications
- STUB 'WINSTUB.EXE' ; Generates error message if application
- ; is run without Windows
-
- ;CODE can be moved in memory and discarded/reloaded
- CODE PRELOAD MOVEABLE DISCARDABLE
-
- ;DATA must be MULTIPLE if program can be invoked more than once
- DATA PRELOAD MOVEABLE MULTIPLE DISCARDABLE
-
- HEAPSIZE 1024
- STACKSIZE 5120 ; recommended minimum for Windows applications
-
- ; All functions that will be called by any Windows routine
- ; MUST be exported.
-
- EXPORTS
- MyMainWndProc @1
- TabAmount @2
-
-
-
-
- [LISTING FOUR]
-
- #include <windows.h>
- #include "progedit.h"
-
- ProgEdit ICON PROGEDIT.ICO
-
- TabAmount DIALOG 11, 25, 75, 24
- CAPTION "Tab Amount"
- STYLE WS_POPUPWINDOW | WS_CAPTION
- BEGIN
- CONTROL "Tab Amt:", -1, "static",
- SS_RIGHT | WS_CHILD,
- 10, 6, 30, 12
- CONTROL "4", IDC_TABAMT, "edit",
- ES_LEFT | WS_BORDER | WS_TABSTOP | WS_CHILD,
- 45, 6, 20, 12
- END
-
-
-
-
-
- [LISTING FIVE]
-
- /*****************************************************************************
- PROGRAM: ProgEdit -- AUTHOR: Mike Klein -- VERSION: 1.0
- FILE: progedit.exe -- REQUIREMENTS: Windows 3.x
- PURPOSE: Example of adding a menu item to a "foreign" application. In this
- case, the program is Windows' NotePad, and the extension added is a definable
- tab stop setting to Notepad's menu bar.
- *****************************************************************************/
-
- #define _WINDOWS
- #define NOCOMM
-
- #include <windows.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "progedit.h"
-
- /* Handles & vars needed for ProgEdit */
- HANDLE hInstProgEdit;
- FARPROC lpfnMyMainWndProc;
- /* Handles & vars needed for Notepad */
- HMENU hMenuNotepad;
- HWND hWndNotepadMain;
- HWND hWndNotepadEdit;
- FARPROC lpfnNotepadMainWndProc;
-
- int TabAmt;
-
- BYTE Text[100];
-
- /*****************************************************************************
- FUNCTION: WinMain
- PURPOSE : Calls initialization function, processes message loop
- *****************************************************************************/
- int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
- int nCmdShow)
- {
- MSG msg;
- struct
- {
- WORD wAlwaysTwo;
- WORD wHowShown;
- }
- HowToShow;
-
- struct
- {
- WORD wEnvSeg;
- LPSTR lpCmdLine;
- LPVOID lpCmdShow;
- DWORD dwReserved;
- }
- ParameterBlock;
- HowToShow.wAlwaysTwo = 2;
- HowToShow.wHowShown = SW_SHOWNORMAL;
- ParameterBlock.wEnvSeg = 0;
- ParameterBlock.lpCmdLine = "";
- ParameterBlock.lpCmdShow = (LPVOID) &HowToShow;
- ParameterBlock.dwReserved = NULL;
- hInstProgEdit = hInstance;
-
- /* Run a copy of NotePad */
- if(LoadModule("notepad.exe", (LPVOID) &ParameterBlock) < 32)
- {
- MessageBox(NULL, "Running instance of NotePad", "ERROR",
- MB_OK | MB_ICONSTOP);
- return(FALSE);
- }
-
- /* Get handles to Notepad's two main windows */
- hWndNotepadMain = GetActiveWindow();
- hWndNotepadEdit = GetFocus();
-
- /* Set up different function pointers. Get a ptr to my hWnd func, then
- ** plug it into the other application's struct so it calls my func. Of
- ** course, at end of my func, I call func that I stole in first place. */
- lpfnMyMainWndProc=MakeProcInstance((FARPROC) MyMainWndProc, hInstProgEdit);
- lpfnNotepadMainWndProc=(FARPROC) SetWindowLong(hWndNotepadMain,GWL_WNDPROC,
- (DWORD) lpfnMyMainWndProc);
-
- /* Get handle to Notepad's menu and add Tabs to main menu */
- hMenuNotepad = GetMenu(hWndNotepadMain);
- AppendMenu(hMenuNotepad, MF_STRING, IDC_TABAMT, "&Tabs");
- DrawMenuBar(hWndNotepadMain);
-
- /* Read in tab amt from win.ini */
- GetProfileString("ProgEdit", "Tabs", "4", Text, 2);
- TabAmt = (HIWORD(GetDialogBaseUnits()) * (Text[0] - '0')) / 4;
- SendMessage(hWndNotepadEdit, EM_SETTABSTOPS, 1, (LONG) (LPINT) &TabAmt);
-
- /* Acquire and dispatch messages until a WM_QUIT message is received. */
- while(GetMessage(&msg, NULL, NULL, NULL))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- FreeProcInstance(lpfnMyMainWndProc);
- return(FALSE);
- }
-
- /*****************************************************************************
- FUNCTION: MyMainWndProc
- PURPOSE : Filter/replacement function for Notepad's MainWndProc()
- *****************************************************************************/
- LONG FAR PASCAL MyMainWndProc(HWND hWnd,unsigned wMsg,WORD wParam,LONG lParam)
- {
- FARPROC lpProc;
- switch(wMsg)
- {
- case WM_COMMAND :
- switch(wParam)
- {
- case IDC_TABAMT :
- /* Set tab stops in edit window */
- lpProc = MakeProcInstance(TabAmount, hInstProgEdit);
- DialogBox(hInstProgEdit, "TabAmount", hWnd, lpProc);
- FreeProcInstance(lpProc);
- break;;
- default :
- break;
- }
- break;
- case WM_DESTROY :
- SendMessage(hWndNotepadMain, WM_QUIT, 0, 0L);
- PostQuitMessage(0);
- break;
- default :
- break;
- }
- return(CallWindowProc(lpfnNotepadMainWndProc, hWnd, wMsg, wParam, lParam));
- }
-
- /*****************************************************************************
- FUNCTION: TabAmount
- PURPOSE : Processes messages for edit window that gets tab amount
- *****************************************************************************/
- BOOL FAR PASCAL TabAmount(HWND hWnd, unsigned wMsg, WORD wParam, LONG lParam)
- {
- switch(wMsg)
- {
- case WM_INITDIALOG :
- /* Display the current tab setting */
- SendDlgItemMessage(hWnd, IDC_TABAMT, EM_LIMITTEXT, 1, 0L);
- SetDlgItemInt(hWnd, IDC_TABAMT, (TabAmt * 4) /
- HIWORD(GetDialogBaseUnits()), FALSE);
- return(TRUE);
- case WM_COMMAND :
- switch(wParam)
- {
- case IDOK :
- case IDCANCEL :
-
- /* Get number of tabs and calculate it in dialog units */
- GetDlgItemText(hWnd, IDC_TABAMT, Text, sizeof(Text));
- TabAmt = (HIWORD(GetDialogBaseUnits()) * (Text[0] - '0')) / 4;
- /* Set the tab stops in the edit window */
- SendMessage(hWndNotepadEdit, EM_SETTABSTOPS, 1,
- (LONG) (LPINT) &TabAmt);
- InvalidateRect(hWndNotepadEdit, NULL, TRUE);
- UpdateWindow(hWndNotepadEdit);
- /* Save the tab amt in WIN.INI profile */
- WriteProfileString("ProgEdit", "Tabs", Text);
- EndDialog(hWnd, TRUE);
- return(TRUE);
- default :
- break;
- }
- break;
- default :
- break;
- }
- return(FALSE);
- }
-
-
-
- [LISTING SIX]
-
- # Standard Windows make file. The utility MAKE.EXE compares the
- # creation date of the file to the left of the colon with the file(s)
- # to the right of the colon. If the file(s) on the right are newer
- # then the file on the left, Make will execute all of the command lines
- # following this line that are indented by at least one tab or space.
- # Any valid MS-DOS command line may be used.
-
- # This line allows NMAKE to work as well
- all: subclass.exe
-
- # Update the resource if necessary
- subclass.res: subclass.rc subclass.h subclass.ico
- rc -r subclass.rc
-
- # Update the object file if necessary
- subclass.obj: subclass.c subclass.h
- cl -W4 -c -AS -Gsw -Oad -Zip subclass.c
-
- # Update the executable file if necessary, and if so, add the resource back in.
- subclass.exe: subclass.obj subclass.def
- link /NOD /CO subclass,,, libw slibcew, subclass.def
- rc subclass.res
-
- # If the .res file is new and the .exe file is not, update the resource.
- # Note that the .rc file can be updated without having to either
- # compile or link the file.
- subclass.exe: subclass.res
- rc subclass.res
-
-
-
-
- [LISITNG SEVEN]
-
-
- /* Standard defines */
- #define FIRST (0L)
- #define LAST (0x7fff7fffL)
- #define ALL (0x00007fffL)
-
- #define IDC_LISTBOX 100
- #define IDC_INPUTBOX 100
-
- /* Function prototypes */
- int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
-
- LONG FAR PASCAL MainWndProc(HWND, unsigned, WORD, LONG);
- LONG FAR PASCAL HandleListBoxes(HWND, unsigned, WORD, LONG);
- LONG FAR PASCAL HandleEditCtrls(HWND, unsigned, WORD, LONG);
- VOID PASCAL CloseEditWindow(VOID);
- VOID PASCAL OpenEditWindow(DWORD);
-
-
-
-
- [LISTING EIGHT]
-
- ; module-definition file for Megaphone -- used by LINK.EXE
-
- NAME Test ; application's module name
- DESCRIPTION 'Test'
- EXETYPE WINDOWS ; required for all Windows applications
- STUB 'WINSTUB.EXE' ; Generates error message if application
- ; is run without Windows
-
- ;CODE can be moved in memory and discarded/reloaded
- CODE PRELOAD MOVEABLE DISCARDABLE
-
- ;DATA must be MULTIPLE if program can be invoked more than once
- DATA PRELOAD MOVEABLE MULTIPLE
-
- HEAPSIZE 1024
- STACKSIZE 5120 ; recommended minimum for Windows applications
-
- ; All functions that will be called by any Windows routine
- ; MUST be exported.
-
- EXPORTS
- MainWndProc @1
- HandleListBoxes @2
- HandleEditCtrls @3
-
-
-
- [LISTING NINE]
-
- /* Include files needed for .RC file */
- #include "windows.h"
- #include "subclass.h"
-
- /* The program's icon (not that it needs one) */
- SubClass ICON SUBCLASS.ICO
-
- /* Main dialog w/listbox used by SubClass */
- SubClass DIALOG 36, 34, 100, 100
- CAPTION "SubClass"
- CLASS "SubClass"
- STYLE WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | DS_LOCALEDIT
- BEGIN
- CONTROL "", IDC_LISTBOX, "BetterListBox",
- LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT |
- WS_BORDER | WS_VSCROLL | WS_CHILD,
- 10, 10, 80, 80
- END
-
-
- [LISTING TEN]
-
- /*****************************************************************************
- PROGRAM: SubClass -- AUTHOR: Mike Klein -- VERSION: 1.0
- FILE : subclass.exe -- REQUIREMENTS: Windows 3.x
- PURPOSE: An example of a subclassed listbox, providing enhanced input
- and data-entry facilities.
- *****************************************************************************/
-
- /* Some std defines needed */
- #define _WINDOWS
- #define NOCOMM
-
- /* INCLUDE files */
- #include <windows.h>
- #include "subclass.h"
-
- /* Global variables */
- HANDLE hInstSubClass;
- HWND hDlgSubClass;
- HWND hWndListBox;
- HWND hWndEdit;
-
- int CurrentIndex;
- int NumListBoxItems;
- RECT CurrentItemRect;
-
- BOOL InsideEditMode = FALSE;
- DWORD dwEditPos;
-
- BYTE InputString[50];
-
- /* Far pointers to Windows' class functions for listboxes and edit ctrls */
- FARPROC lpfnListBox;
- FARPROC lpfnEditCtrl;
-
- /*****************************************************************************
- FUNCTION: WinMain
- PURPOSE : Calls initialization function, processes message loop
- *****************************************************************************/
- int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,
- int nCmdShow)
- {
- WNDCLASS wc;
- MSG msg;
- if(!hPrevInstance)
- {
- hInstSubClass = hInstance;
- /* Fill in window class structure with parameters that describe the
- ** main window */
- wc.style = CS_DBLCLKS;
- wc.lpfnWndProc = MainWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = DLGWINDOWEXTRA;
- wc.hInstance = hInstSubClass;
- wc.hIcon = LoadIcon(hInstSubClass, "SubClass");
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "SubClass";
- if(!RegisterClass(&wc))
- return(FALSE);
- /* Fill in window class structure with parameters that describe our
- ** custom list box -- BetterListBox */
- wc.style = CS_DBLCLKS;
- wc.lpfnWndProc = HandleListBoxes;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstSubClass;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "BetterListBox";
- if(!RegisterClass(&wc))
- return(FALSE);
- /* Fill in window class structure with parameters that describe our
- ** custom edit control -- BetterEditCtrl */
- wc.style = CS_DBLCLKS;
- wc.lpfnWndProc = HandleEditCtrls;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstSubClass;
- wc.hIcon = NULL;
- wc.hCursor = LoadCursor(NULL, IDC_IBEAM);
- wc.hbrBackground = GetStockObject(WHITE_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = "BetterEditCtrl";
- if(!RegisterClass(&wc))
- return(FALSE);
- /* Get information on listbox class, so we can find out what its
- ** class window function is. */
- if(GetClassInfo(NULL, "listbox", &wc) == FALSE)
- return(FALSE);
- else
- lpfnListBox = (FARPROC) wc.lpfnWndProc;
- /* Get information on edit control class, so we can find out what its
- ** class window function is. */
- if(GetClassInfo(NULL, "edit", &wc) == FALSE)
- return(FALSE);
- else
- lpfnEditCtrl = (FARPROC) wc.lpfnWndProc;
-
- /* Create the main window */
- if((hDlgSubClass = CreateDialog(hInstSubClass, "SubClass",
- NULL, 0L)) == NULL)
- {
- return(FALSE);
- }
- /* Get an oft used handle */
- hWndListBox = GetDlgItem(hDlgSubClass, IDC_LISTBOX);
- /* Put in some test strings. */
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "computer");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "telephone");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "lcd");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "ochessica");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "heeyah");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "video");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "smoke");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "sky");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "lovely");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "windows");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "nunez");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "beer");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "pug");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "query");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "remote");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "party");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "mixer");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "skate");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "varied");
- SendMessage(hWndListBox, LB_ADDSTRING, 0, (LONG) (LPSTR) "interests");
- /* Give the listbox an initial selection */
- SendMessage(hWndListBox, LB_SETCURSEL, 0, 0L);
- ShowWindow(hDlgSubClass, nCmdShow);
- UpdateWindow(hDlgSubClass);
- }
- else
- {
- /* If there was another instance of SubClass running, then switch
- ** to it by finding any window of class = "SubClass". Then, if it's
- ** an icon, open the window, otherwise just make it active. */
- hDlgSubClass = FindWindow("SubClass", NULL);
- if(IsIconic(hDlgSubClass))
- ShowWindow(hDlgSubClass, SW_SHOWNORMAL);
- SetActiveWindow(hDlgSubClass);
- return(FALSE);
- }
- /* Acquire and dispatch messages until a WM_QUIT message is received. */
- while(GetMessage(&msg, NULL, NULL, NULL))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- /*****************************************************************************
- FUNCTION: MainWndProc
- PURPOSE : Processes messages for SubClass dialog box
- *****************************************************************************/
- LONG FAR PASCAL MainWndProc(HWND hWnd, unsigned wMsg, WORD wParam,
- LONG lParam)
- {
- switch(wMsg)
- {
- case WM_CLOSE :
- DestroyWindow(hDlgSubClass);
- return(0L);
- case WM_SETFOCUS :
- SetFocus(hWndListBox);
- return(0L);
- case WM_DESTROY :
- PostQuitMessage(0);
- return(0L);
- default :
- break;
- }
- return(DefDlgProc(hWnd, wMsg, wParam, lParam));
- }
-
- /*****************************************************************************
- FUNCTION: OpenEditWindow
- PURPOSE : Opens edit window inside listbox
- *****************************************************************************/
- VOID PASCAL OpenEditWindow(DWORD CharSel)
- {
- /* Flag telling us were in edit mode */
- InsideEditMode = TRUE;
- /* Find out current index into listbox */
- CurrentIndex = (int) SendMessage(hWndListBox, LB_GETCURSEL, 0, 0L);
- if(CurrentIndex == LB_ERR)
- CurrentIndex = 0;
- /* Find out what the text is in selected listbox cell */
- SendMessage
- (
- hWndListBox,
- LB_GETTEXT,
- CurrentIndex,
- (LONG) (LPSTR) InputString
- );
- /* Get client dimensions of listbox cell with respect to the entire
- ** listbox and create an edit window right inside of it. */
- SendMessage
- (
- hWndListBox,
- LB_GETITEMRECT,
- CurrentIndex,
- (DWORD) (LPRECT) &CurrentItemRect
- );
- hWndEdit = CreateWindow
- (
- "BetterEditCtrl",
- "",
- ES_AUTOHSCROLL | ES_LEFT | WS_VISIBLE | WS_CHILD,
- CurrentItemRect.left + 2,
- CurrentItemRect.top,
- CurrentItemRect.right - CurrentItemRect.left - 2,
- CurrentItemRect.bottom - CurrentItemRect.top,
- hWndListBox,
- IDC_INPUTBOX,
- hInstSubClass,
- 0L
- );
- /* Pre-fill the edit control with what was in the listbox cell */
- SetWindowText(hWndEdit, InputString);
- SetFocus(hWndEdit);
- SendMessage(hWndEdit, EM_SETSEL, 0, CharSel);
- }
-
- /*****************************************************************************
- FUNCTION: CloseEditWindow
- PURPOSE : Closes edit window inside listbox
- *****************************************************************************/
- VOID PASCAL CloseEditWindow(VOID)
- {
- /* Flag telling us were aren't in edit mode anymore */
- InsideEditMode = FALSE;
- /* Get text of what was entered into edit control */
- GetWindowText(hWndEdit, InputString, sizeof(InputString));
- if(!GetWindowTextLength(hWndEdit))
- {
- DestroyWindow(hWndEdit);
- SendMessage(hWndListBox, WM_KEYDOWN, VK_DELETE, 0L);
- return;
- }
- /* Turn redrawing for the listbox off. */
- SendMessage(hWndListBox, WM_SETREDRAW, 0, 0L);
- /* Find out the RECT of the currently selected listbox item */
- SendMessage(hWndListBox, LB_GETITEMRECT, CurrentIndex, (DWORD) (LPRECT)
- &CurrentItemRect);
- /* Delete the old string and add the new one */
- SendMessage(hWndListBox, LB_INSERTSTRING, CurrentIndex,
- (LONG) (LPSTR) InputString);
- SendMessage(hWndListBox, LB_DELETESTRING, CurrentIndex + 1, 0L);
- /* Destroy the old edit window. */
- DestroyWindow(hWndEdit);
- /* Validate the whole listbox and then invalidate only the list box rect
- ** that we put the edit window into. */
- ValidateRect(hWndListBox, NULL);
- InvalidateRect(hWndListBox, &CurrentItemRect, TRUE);
-
- /* Turn re-drawing for the listbox back on and send a WM_PAINT for the
- ** entry changes to take effect. */
- SendMessage(hWndListBox, WM_SETREDRAW, 1, 0L);
- UpdateWindow(hWndListBox);
- SetFocus(hWndListBox);
- }
-
- /*****************************************************************************
- FUNCTION: HandleListBoxes
- PURPOSE : Process keystrokes and mouse for list boxes
- *****************************************************************************/
- LONG FAR PASCAL HandleListBoxes(HWND hWnd, unsigned wMsg, WORD wParam,
- LONG lParam)
- {
- switch(wMsg)
- {
- case WM_LBUTTONDBLCLK :
-
- /* Go into edit mode and put caret at end of edit ctrl. */
- if(SendMessage(hWnd, LB_GETCOUNT, 0, 0L))
- {
- OpenEditWindow(LAST);
- }
- return(0L);
- case WM_LBUTTONDOWN :
- if(InsideEditMode)
- {
- /* Find out cursor pos from the edit ctrl, so we can
- ** use same positioning for cell were moving into */
- dwEditPos = SendMessage(hWndEdit, EM_GETSEL, 0, 0L);
- CloseEditWindow();
- /* Tell listbox to move cur ptr up or down based on
- ** the mouse position, and open a new edit window */
- SendMessage(hWndListBox, wMsg, wParam, lParam);
- OpenEditWindow
- (
- MAKELONG(LOWORD(dwEditPos), LOWORD(dwEditPos))
- );
- return(0L);
- }
- break;
- case WM_MBUTTONDBLCLK :
- case WM_RBUTTONDBLCLK :
- /* Make middle & right mouse buttons like left mouse button. */
- SendMessage(hWnd, WM_LBUTTONDBLCLK, wParam, lParam);
- break;
- case WM_MBUTTONDOWN :
- case WM_RBUTTONDOWN :
- /* Make middle & right mouse buttons like left mouse button. */
- SendMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
- SendMessage(hWnd, WM_LBUTTONUP, wParam, lParam);
- break;
- case WM_KEYDOWN :
- switch(wParam)
- {
- case VK_RETURN :
- /* Enter was pressed, so go into edit mode and put the
- ** caret at the end of the edit ctrl */
- if(SendMessage(hWnd, LB_GETCOUNT, 0, 0L))
- {
- OpenEditWindow(LAST);
- }
- return(0L);
- case VK_INSERT :
- /* The INS key (add a new string). First, get currently
- ** selected entry. If none exists, assume that focus is on
- ** the first cell */
- CurrentIndex =
- (int) SendMessage(hWnd, LB_GETCURSEL, 0, 0L);
- if(CurrentIndex == LB_ERR)
- {
- CurrentIndex = 0;
- }
- /* Find out what the text is in selected listbox cell */
- if(SendMessage(hWnd, LB_GETCOUNT, 0, 0L))
- {
- SendMessage
- (
- hWnd,
- LB_GETTEXT,
- CurrentIndex,
- (LONG) (LPSTR) InputString
- );
- }
- else
- {
- /* If nothing's in the listbox, then copy a null to
- ** the edit control. */
- InputString[0] = '\0';
- }
-
- /* Insert new entry */
- SendMessage
- (
- hWnd,
- LB_INSERTSTRING,
- CurrentIndex,
- (LONG) (LPSTR) InputString
- );
- /* Let our "edit current cell" function take over */
- OpenEditWindow(ALL);
- return(0L);
- case VK_DELETE :
- /* The DEL key. If no items are in the listbox, then
- ** return. Else, get the currently selected item. */
- if(!(NumListBoxItems = (int)
- SendMessage(hWnd, LB_GETCOUNT, 0, 0L)))
- {
- break;
- }
- if((CurrentIndex = (int)
- SendMessage(hWnd, LB_GETCURSEL, 0, 0L)) == LB_ERR)
- {
- CurrentIndex = 0;
- }
- /* Delete the string. Tried to get rid of annoying
- ** focus rect; couldn't. Too many inconsitencies in
- ** the way Windows handles list and combo boxes. */
- SendMessage(hWnd, LB_DELETESTRING, CurrentIndex, 0L);
- if(CurrentIndex == NumListBoxItems - 1)
- {
- --CurrentIndex;
- }
- /* Reset our listbox selection. */
- SendMessage(hWnd, LB_SETCURSEL, CurrentIndex, 0L);
- return(0L);
- default :
- break;
- }
- break;
- default :
- break;
- }
- /* Return any unprocessed messages to window's original class procedure. */
- return(CallWindowProc(lpfnListBox, hWnd, wMsg, wParam, lParam));
- }
-
- /*****************************************************************************
- FUNCTION: HandleEditCtrls
- PURPOSE : Process keystrokes and mouse for edit controls
- *****************************************************************************/
- LONG FAR PASCAL HandleEditCtrls(HWND hWnd, unsigned wMsg, WORD wParam,
- LONG lParam)
- {
- switch(wMsg)
- {
- case WM_LBUTTONDBLCLK :
- /* Turn of edit mode, closing the edit window */
- CloseEditWindow();
- return(0L);
- case WM_KEYDOWN :
- switch(wParam)
- {
- case VK_RETURN :
- /* Turn of edit mode, closing the edit window */
- CloseEditWindow();
- return(0L);
- case VK_DELETE :
- /* Delete a character if one exists in the edit ctrl.
- ** Otherwise, if the cell is blank, delete the entire
- ** cell. */
- if(!GetWindowTextLength(hWnd))
- {
- CloseEditWindow();
- SendMessage(hWndListBox, wMsg, wParam, lParam);
- return(0L);
- }
- break;
- case VK_DOWN :
- case VK_UP :
- case VK_PRIOR :
- case VK_NEXT :
- /* Find out cursor pos from edit ctrl, so we can
- ** use same positioning for cell we're moving into */
- dwEditPos = SendMessage(hWndEdit, EM_GETSEL, 0, 0L);
- CloseEditWindow();
- /* Tell listbox to move cur ptr up or down, and
- ** open an edit window at the new pos. */
- SendMessage(hWndListBox, wMsg, wParam, lParam);
- OpenEditWindow
- (
- MAKELONG(LOWORD(dwEditPos), LOWORD(dwEditPos))
- );
- return(0L);
- default :
- break;
- }
- break;
- default :
- break;
- }
- /* Return any unprocessed messages to window's original class procedure. */
- return(CallWindowProc(lpfnEditCtrl, hWnd, wMsg, wParam, lParam));
- }
-