Home |
13A. MakeApp Examples Example Code for MakeApp, with Drag and Drop from Explorer. |
Home |
Here you can look at some code that will give examples for using the functions in the MakeApp.pas unit. Many of the functions were explained in the InUnits Lesson, and the added functions for MakeApp are explained in the Lesson about the MakeApp Unit. So I will not give any more information here about MakeApp functions. You can look at the code and comments in the UseMakeAppU.pas file code below for information about what the code is doing. There is an API method for simple Drag and Drop from Explorer, which I will talk about here, using the DragAcceptFiles( ) procedure. |
Explorer Drag and Drop using DragAcceptFiles( ) Procedure Doing drag and drop between two different processes (programs) is usually done with the system COM interfaces of IDropSource, and IDropTarget. . But to do a simple file path drag and drop from explorer, the API offers a way to do it without using the IDropSource or IDropTarget interfaces or any COM methods. You can use the DragAcceptFiles( ) procedure for a window's handle, and the operating system will implement and use (translate) the COM interfaces, then send the system message WM_DROPFILES to that window, whenever files are dropped on that window. When this WM_DROPFILES message is received by a window, you can call two functions to get information about the file paths dropped on the window. The DragQueryFile( ) function is used to get the PChar strings for each file path in the drop, the DragQueryPoint( ) function gets the position of the cursor (TPoint) in the window where the drop happened. Whenever you call one of these functions in a WM_DROPFILES message the system will use the drop Interfaces, so you MUST call the DragFinish( ) function, to tell the system to release and free any COM interfaces or system memory that the system may have used for this. Lets look at the parameters for the DragAcceptFiles( ) function which is defined as - procedure DragAcceptFiles( Wnd: HWND; // handle to the window for drag and drop Accept: BOOL // accept drop option );This procedure is an OS Shell function so you must have ShellApi in your uses clause. The first parameter is the Handle of the window that you want this procedure to affect. The second parameter is a Bool value that is set to True to have the window accept drag and drop, , and set to False to remove the window from drag and drop. When DragAcceptFiles( ) is set to True for a window, and an explorer file drop happens on that window, the WM_DROPFILES message is sent to that window. WM_DROPFILES Message DragQueryFile( ) function function DragQueryFile( Drop: HDROP; // drop handle from WParam FileIndex: UINT; // index of file path in the drop info FileName: PChar; // buffer that recieves the filename cb: UINT // size of buffer for filename * ): UINT;This function has three uses 1 - it can return the number (count) of file path names in the drop The Drop parameter is always a drop handle from the system, which is the WParam in a WM_DROPFILES message.
This function will get the mouse cursor position for the Drop, , if the Drop is in the Controls client area. Let's look at the DragQueryPoint( ) function - function DragQueryPoint( Drop: HDROP; // handle to structure for dropped files var Point: TPoint // TPoint for control mouse coordinates ):The Drop parameter is always a drop handle from the system, which is the WParam in a WM_DROPFILES message. The Point parameter will be filled with the control's X an Y position of the mouse cursor of the Drop position on that control. This only happens if the Drop position in on the Client area of the control. If the drop happens on the border or scroll bars, then this DragQueryPoint( ) function returns FALSE and the TPoint if filled with zeros. So you should always check the result of the DragQueryPoint( ) function. DragFinish( ) procedure procedure DragFinish(Drop: HDROP);If you set a window to recieve explorer drag and drop with DragAcceptFiles( ), be sure to process the WM_DROPFILES message and call DragFinish( ). Example code for a WM_DROPFILES message - WM_DROPFILES: begin //the WParam has the file drop Handle in it StrSize := 256; // StrSize is an Cardinal variable Count := DragQueryFile(WParam, MaxDWord, nil, StrSize); {DragQueryFile is called 3 times to get 3 different data information. With MaxDWord and nil, it will return the number of file names in the Drop, to the Count variable, an Integer} for i := Zero to Count- One do // i is Integer used as the Index for the DragQueryFile begin StrSize := DragQueryFile(WParam, i, nil, StrSize); // StrSize will have the number of Charaters {DragQueryFile will return the length of the file name string, if you have the Index number and also have nil for the PChar} if StrSize < One then Continue; SetLength(StrLB, StrSize); // StrLB is a String variable DragQueryFile(WParam,i,PChar(StrLB), StrSize + One); {DragQueryFile will place the file name in PathStr if the PChar is not nil} SendMessage(hListBoxPan, LB_ADDSTRING, Zero, Integer(PChar(StrLB))); // add the file path to a list box end; DragFinish(WParam); // IMPORTANT, always call DragFinish // IMPORTANT DO NOT LET DefWindowProc be called if you do the WM_DROPFILES Exit; // You MUST Exit end;You can see a code example for WM_DROPFILES in the DoListDrop procedure of the UseMakeAppU.pas example below. |
This program will show you how to use the "Make" functions in the MakeApp Unit and to use the DragAcceptFiles( ) procedure with it's WM_DROPFILES message. The Drag and Drop functions are explained above, you should look at the DoListDrop( ) procedure in the code below for an example of WM_DROPFILES message handling. The "Make" functions in the MakeApp unit are all explained in the Lesson 12, MakeApp Unit page, so you can go to that page if you need information about them. Most of them are not difficult to use, but the MakeSubMenu( ) and it's ItemList parameter may take more to learn, so you should look at the different sub-menus created in the MakeProgram( ) function in the code below. There are two "Panels" created in this, and they each need a TPanelFunc function to handle their messages. You can look at their TPanelFunc message functions - PanelMessFunc and PanelMessFunc2 To show you how to have a child control that had focus, to regain focus when the main Window (Form) becomes Active after losing keyboard focus, I have included an integer variable in the UseMakeAppU.pas Unit called ActControl. This is used to store the Active (Focus) control handle when the form loses keyboard focus. You can look in the form's MessageFunc for the WM_ACTIVATE, WM_SETFOCUS, WM_KILLFOCUS, and WM_ACTIVATEAPP messages to see how to store and re-focus a child control There are comments in the unit code that should give information about how and why I do those things. Below is the code for the parts of this UseMakeApp program |
Code for the Theme.RC , resource creation file
One line of code -
1 24 "Theme.xml" |
Code for the Theme.xml manifest document
Six lines of code -
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="Co.Prd.Prg" type="win32" /> <dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*" /> </dependentAssembly></dependency></assembly> |
You will need to compile the Theme.RC file with the Delphi brcc32.exe resource
compiler to get the Theme.RES file used in the next code
Code For The UseMakeApp.dpr Program File
This is like the code for the InUnits program
program UseMakeApp; uses MakeApp, UseMakeAppU; {$R *.RES} {$R Theme.RES} // Theme.RES has a win XP theme manifest begin if MakeProgram then // MakeProgram in UseMakeAppU RunMsgLoop; // RunMsgLoop in MakeApp end. |
Code For The UseMakeAppU.pas Unit
See the comments in this code for more information
unit UseMakeAppU; {this unit will contain the code for the UseMakeApp program the code here will give examples of using the functions in the MakeApp unit and system Drag and Drop with the DragAcceptFiles function} interface var hForm1: Integer = 0; // handle of Main Window (Form) function MakeProgram: Boolean; {the MakeProgram function will call some functions in MakeApp.pas to create the windows and controls for this Application. If there is a creation error for the main window, it returns False} implementation uses Windows, Messages, ShellApi, MakeApp, SmallUtils; // you add the ShellApi to uses in order to use the Shell Drag and Drop const One = 1; // I include this because the number 1 is used so many times ColorPan: Cardinal = $29EEF1; // this is the BASE color for the hPanel1 // below are the constants for control ID numbers ID_ExitBut = 1000; ID_PanelBut = 1001; ID_PanelBut2 = 1002; ID_Edit1 = 1003; // below are the constants for menu Items ID m_TopItem = 10; m_Second = 11; m_Add2ListBox = 12; m_ChangeEdit = 13; m_Exit = 14; m_MoveP1 = 20; m_MoveP2 = 21; m_ColorP1 = 22; m_MessBox = 30; m_AddedItem = 60; var hCombo, Font1, FontP, hListBox1, hListBoxPan, hEdit1, hPanel1, hPanel2, ActControl: Integer; { ActControl is used to to store the Active Control Handle, which is given focus when the Form regains keyboard focus on application activate} PanelColor: Cardinal = Zero; // holds the current color painted on hPanel1 pListProc: Pointer; // Sub Class function pointer procedure DoListDrop(wParam: Integer); var PathStr: String; Count, Index, i: Integer; StrSize: Cardinal; DropPnt: TPoint; begin {this is the procedure to handle the Drag and Drop message on the hListBox1, the WParam will have the hDrop, file drop Handle in it} StrSize := 256; {DragQueryPoint will get the point location of the "Drop" on the Control} if DragQueryPoint(WParam, DropPnt) then begin {I get the List Box Index for the Location where the drop mouse button was released since DragQueryPoint will get the cursor position on hListBox1 where the Drop happened} Index := CallWindowProc(pListProc, hListBox1, LB_ITEMFROMPOINT, Zero, MAKELPARAM(DropPnt.x, DropPnt.y)) and $FFFF; end else Index := Zero; {DragQueryPoint only returns True if drop was on the Client area of the control, drop on the List Box scroll bars will return False} Count := DragQueryFile(WParam, MaxDWord, nil, StrSize); {DragQueryFile is called 3 times to get 3 different data information. With MaxDWord and nil, it will return the number of file names in the Drop} for i := Zero to Count- One do begin StrSize := DragQueryFile(WParam, i, nil, StrSize); {DragQueryFile will return the length of the file name string, if you have the Index number and also have nil for the FileName PChar} if StrSize < One then Continue; SetLength(PathStr, StrSize); // StrSize will have the number of Charaters DragQueryFile(WParam,i,PChar(PathStr), StrSize + One); {DragQueryFile will place the file name in PathStr if the FileName PChar is not nil} // add the dropped file path to hListBox1 CallWindowProc(pListProc, hListBox1, LB_INSERTSTRING, Index, Integer(PChar(PathStr))); // I use CallWindowProc instsead of SendMessage code below //SendMessage(hListBox1, LB_INSERTSTRING, Zero, Integer(PChar(PathStr))); end; DragFinish(WParam); {IMPORTANT - you MUST call DragFinish to end and release the Drag methods and system resources the system is using for the drop operation} end; function ListBFunc(hWnd, Msg, WParam, LParam: Integer): Integer; stdcall; begin if Msg = WM_DROPFILES then begin {the Only message I process for this List box is the drag and drop files Message} DoListDrop(WParam); Result := Zero; // IMPORTANT DO NOT LET CallWindowProc be called if you do the WM_DROPFILES Exit; // You MUST Exit end; Result := CallWindowProc(pListProc,hWnd,Msg,wParam,lParam); end; function PanelMessFunc(iMsg,wParam,lParam:Integer):Integer; var PaintS: TPaintStruct; begin {For a MakeApp Panel, you will need to give a TPanelFunc function in the MakePanel creation function, if you want to process that panel messages. This is the TPanelFunc function for hPanel1} {The Result of This function is passed back to the system as the Result of this panel's window message proc, and the DefWindowProc will NOT be called, EXCEPT if the Result is -2 here} Result := -2; { the result of -2 here, will call the DEFAULT system message processing (DefWindowProc) in this TPanelFunc and return that Result} case iMsg of WM_PAINT: begin { there is NO hWnd paramteter in the TPanelFunc like in the window Message functions, but you should know the panel's handle from the MakePanel function where you assign this TPanelFunc} BeginPaint(hPanel1, PaintS); // use the hPanel1 handle // the PatBlt function is used to change the color of this panel SelectObject(PaintS.hDC, CreateSolidBrush(PanelColor)); PatBlt(PaintS.hDC,PaintS.rcPaint.Left,PaintS.rcPaint.Top, PaintS.rcPaint.Right, PaintS.rcPaint.Bottom, PATCOPY); DeleteObject(SelectObject(PaintS.hDC, GetStockObject(NULL_BRUSH))); // the Rectangle functions draws a simple border for this panel Rectangle(PaintS.hdc,Zero,Zero,150, 106); SelectObject(PaintS.hDC, GetStockObject(WHITE_PEN)); Rectangle(PaintS.hdc,Zero,Zero,160, 110); SetBkMode(PaintS.hdc, TRANSPARENT); SSelectObject(PaintS.hdc, FontP); TextOut(PaintS.hdc,30,42, 'Click on this Panel',19); EndPaint(hPanel1,PaintS); Result := Zero; // Does NOT allow DefWindowProc to be called // if Result is NOT -2 then default system message processing is NOT called end; WM_COMMAND: if LOWORD(wParam) = ID_PanelBut then SetWindowText(hEdit1, 'Do Edit Text'); WM_LBUTTONDOWN: SetWindowText(hEdit1, 'Panel Click'); // the WM_LBUTTONDOWN above is like a click event for this panel end; end; function PanelMessFunc2(iMsg,wParam,lParam:Integer):Integer; var PaintS: TPaintStruct; begin //This is the TPanelFunc function for hPanel1 Result := -2; // -2 will call the Default system message processing case iMsg of WM_PAINT: begin BeginPaint(hPanel2, PaintS); // use the hPanel2 handle SetBkColor(PaintS.hdc, $6A92FF); SelectObject(PaintS.hdc, VarFont); TextOut(PaintS.hdc,50,32, ' Panel Label ',13); EndPaint(hPanel2,PaintS); Result := Zero; // Does NOT allow DefWindowProc to be called end; WM_COMMAND: if LOWORD(wParam) = ID_PanelBut2 then MessageBox(hForm1, 'Panel Button Click', 'Click Button', MB_ICONINFORMATION); end; end; procedure MenuClick; begin // just a messagebox function for several menu Items MessageBox(hForm1, 'Menu Item Click', 'Menu Click', MB_ICONINFORMATION); end; procedure ShutDown; begin DragAcceptfiles(hListBox1, False); DragAcceptfiles(hForm1, False); {some MS code examples tell you to call DragAcceptfiles with False, if you call it with True} PostQuitMessage(Zero); end; function MessageFunc(hWnd,iMsg,wParam,lParam:Integer):Integer; stdcall; var PaintS: TPaintStruct; posRect: TRect; Count, StrSize, i: Integer; StrLB: String; begin Result := Zero; case iMsg of WM_DESTROY: ShutDown; WM_ACTIVATE: if LOWORD(wParam) = WA_INACTIVE then begin {there are several messages where I get the current control that has focus and assign it's handle to ActControl} ActControl := GetFocus; // can be zero or hWnd if (ActControl = Zero) or (ActControl = hWnd) then ActControl := hEdit1; end; WM_SETFOCUS: SetFocus(ActControl); {when this form is activated it gets the WM_SETFOCUS message, but NO control is given focus, so to have the last control regain focus use the SetFocus function for ActControl} WM_KILLFOCUS: begin // do GetFocus for current control ActControl := GetFocus; if ActControl = Zero then ActControl := hEdit1; end; WM_PAINT: begin BeginPaint(hWnd, PaintS); SetBkMode(PaintS.hdc, TRANSPARENT); SelectObject(PaintS.hdc, VarFont); TextOut(PaintS.hdc,8,10, 'Drag and Drop on List Box',25); EndPaint(hWnd,PaintS); Exit; end; WM_ACTIVATEAPP: if wParam = Zero then begin {with wParam as zero, the app is being DE-activated so do GetFocus} ActControl := GetFocus; if ActControl = Zero then ActControl := hEdit1; end; WM_COMMAND: if lParam = Zero then begin case LOWORD(wParam) of // menu Item ID m_TopItem: MenuClick; m_Second: MenuClick; m_Add2ListBox: begin Count := SendMessage(hListBox1, LB_GETCOUNT, Zero, Zero); StrLB := 'New LB Item '+Int2Str(Count); SendMessage(hListBox1, LB_ADDSTRING, Zero, Integer(PChar(StrLB))); end; m_ChangeEdit: SetWindowText(hEdit1, 'Edit Text from Menu'); m_Exit: PostMessage(hForm1, WM_CLOSE, Zero, Zero); m_MoveP1: begin GetWindowRect(hPanel1, posRect); ScreenToClient(hForm1, posRect.TopLeft); ScreenToClient(hForm1, posRect.BottomRight); posRect.Bottom := posRect.Bottom - posRect.Top; posRect.Right := posRect.Right - posRect.Left; if posRect.Top = 10 then begin posRect.Top := 51; posRect.Left := 310; end else begin posRect.Top := 10; posRect.Left := 230; end; MoveWindow(hPanel1, posRect.Left,posRect.Top, posRect.Right, posRect.Bottom, True); end; m_MoveP2: begin GetWindowRect(hPanel2, posRect); ScreenToClient(hForm1, posRect.TopLeft); ScreenToClient(hForm1, posRect.BottomRight); posRect.Right := posRect.Right - posRect.Left; if posRect.Left = 106 then posRect.Left := 136 else posRect.Left := 106; MoveWindow(hPanel2, posRect.Left,posRect.Top, posRect.Right, posRect.Bottom - posRect.Top, True); end; m_ColorP1: begin if PanelColor = ColorPan then PanelColor := $EEF100 else PanelColor := ColorPan; InvalidateRect(hPanel1, nil, False); end; m_MessBox: MessageBox(hForm1, 'Message Box menu Click', 'Menu Click', MB_ICONINFORMATION); m_AddedItem: MessageBox(hForm1, 'Added Item menu Click', 'Menu Click', MB_ICONINFORMATION); 88: MessageBox(hForm1, '88 click', 'Menu Click', MB_ICONINFORMATION); end; // case LOWORD(wParam) end else // if lParam = Zero if LOWORD(wParam) = ID_ExitBut then PostMessage(hForm1, WM_CLOSE, Zero, Zero); WM_DROPFILES: begin {the WParam has the file drop Handle in it see the DoListDrop procedure above for info about DragQueryFile} StrSize := 256; Count := DragQueryFile(WParam, MaxDWord, nil, StrSize); for i := Zero to Count- One do begin StrSize := DragQueryFile(WParam, i, nil, StrSize); if StrSize < One then Continue; SetLength(StrLB, StrSize); DragQueryFile(WParam,i,PChar(StrLB), StrSize + One); SendMessage(hListBoxPan, LB_ADDSTRING, Zero, Integer(PChar(StrLB))); end; DragFinish(WParam); // IMPORTANT, always call DragFinish // IMPORTANT DO NOT LET DefWindowProc be called if you do the WM_DROPFILES Exit; // You MUST Exit end; end; // case iMsg Result := DefWindowProc(hWnd,iMsg,wParam,lParam); end; procedure MakeControls; begin PanelColor := ColorPan; // set PanelColor to const Font1 := MakeFont(-15, 10, 'Arial'); // with MakeFont you can create a font with just 3 parameters FontP := MakeFont(-12,Zero, 'Arial', [flBold, flItalic]); DragAcceptFiles(hForm1, True); { to set the Main Form as a window that accepts drag and drop files from explorer, you can call the function DragAcceptFiles with True} hCombo := MakeComboBox(160, 30, 122, 115, hForm1, #255'Combo Box'#0'Next Item'#0'Lower'#0'Middle'#0'Down'#0+ 'Way Down'#0'Way way Down'#0'Lowest'#0); {MakeComboBox uses the ListItems parameter as a #0 delimited string to place several Items in the Combo Box} hPanel1 := MakePanel(330,51, 150, 106, hForm1, PanelMessFunc, 66, psNone); {the MakePanel function will make a Container Window, if you have child controls on the panel, you will need a PanelMessFunc to process their WM_COMMAND messages} // I palce a button and an Edit on this Panel MakeButton(32,10,84, 20, 'Do Edit Text', hPanel1, ID_PanelBut); hEdit1 := CreateWindowEx(WS_EX_CLIENTEDGE,'Edit','Edit Box Text', WS_VISIBLE or WS_CHILD {or ES_AUTOHSCROLL} or WS_TABSTOP, 10,70,130,21,hPanel1,ID_Edit1,hInstance,nil); SendMessage(hEdit1,WM_SETFONT,VarFont,Zero); ActControl := MakeButton(392,238,84, 24, 'E X I T', hForm1, ID_ExitBut, Font1); {ActControl is used to keep track of the Active (Focus) control, which is lost if the Form is not the foreground window} hPanel2 := MakePanel(152,94, 170, 144, hForm1, PanelMessFunc2, 67, psTabEdge); // i put a button and a List Box on the second panel MakeButton(5,6,76, 22, 'Panel Button', hPanel2, ID_PanelBut2); hListBoxPan := MakeListBox(3,50, 159, 86, hPanel2, #255'Panel List Box'#0'list Item'#0); hListBox1 := MakeListBox(4,30, 142, 86, hForm1, #255'List Box 1'#0'List Item'#0'Next List Item'#0'an Item'#0+ 'Middle Item'#0'Item'#0'Low Item'#0'Lowest Item'#0); pListProc := Pointer(SetWindowLong(hListBox1, GWL_WNDPROC, Integer(@ListBFunc))); { Sub-Class the List Box to get the WM_DROPFILES messages, because DragAcceptfiles is called below} DragAcceptfiles(hListBox1, True); {DragAcceptfiles is called for the hListBox1, so it will get it's own Drag and Drop functioning, separate from the hForm1 drag and drop} SetFocus(ActControl); // set focus to Exit Button, which becomes the Active Control, ActControl end; function MakeProgram: Boolean; var menuList: String; hSubM1, hSMenu: Integer; begin Result := False; // start by setting up the main form's window class with SetWinClass if SetWinClass('MakeApp '#9'Class', @MessageFunc) = Zero then Exit; { these next lines of code will create the Main Form's main Menu with the MakeSubMenu function, the sub-menu items will be in the ItemList parameter. You can set item options in the ItemList with a character like #201} {this first call to MakeSubMenu will create a "Sub Menu" for the "Main Menu One" the #251 is used in the ItemList parameter to tell the function to make a Sub Menu that is NOT placed on the main Menu. The ItemList MUST be #0 delimited, with a #0 at the end} hSubM1 := MakeSubMenu(#251'Move Panel 1'#0'Move Panel 2'#0'Change Color Panel 1'#0, id4menu(m_MoveP1,m_MoveP2,m_ColorP1), Zero); if hSubM1 = Zero then begin MessageBox(Zero, 'No Sub Menu - MakeSubMenu Failure', 'ERROR - No menu', MB_ICONERROR); Exit; end; {this menuList string will be used as the ItemList parameter in the MakeSubMenu. It has the #250 as the first character to tell the function that this is a Sub Menu for the main Menu. The first item name "&Main Menu One" will be what is shown on the main Menu} menuList := #250'&Main Menu One'#0'&Top Menu Item'#0#201'&Second Menu Item'+ #0#203'Change Panels'#0'&Add to List Box'#0'&Change Edit'#0#200' '+ #0'E &X I T Alt+F4'#0; {the #201 places a Check on the menu item, and the #200 makes a "Separator" menu Item, and the #203 will add the Sub Menu -> hSubM1} MakeSubMenu(menuList, id4menu(m_TopItem,m_Second,m_Add2ListBox,m_ChangeEdit), id4menu(m_Exit, Zero), hSubM1); {when you call MakeSubMenu above, it automaticaly creates the Form's main Menu and creates the "Main Menu One" sub menu for the main Menu} MakeSubMenu(#250'&Next'#0'Message Box'#0'Do Test'#0'List Box Add'#0'non'#0, id4menu(m_MessBox,m_Second,m_Add2ListBox,66), Zero); {the Next menu above has 4 menu Items and will be added to the mainMenu because it has the #250 first character in ItemList} menuList := #251'mMove Panel 1'#0'mMove Panel 2'#0'mChange Color Panel 1'#0; hSubM1 := MakeSubMenu(menuList, id4menu(m_MoveP1,m_MoveP2,m_ColorP1), Zero); // this Sub Menu will be added to the Big Menu below menuList := #250'&Big Menu'#0'MessageBox'#0#200' '#0'Top Item'#0#202'Next Item'+ #0#203'Sub Menu Item'#0'Some Item'#0#201'This Item'#0'That Item'+ #0'Bottom Item'#0#200' '#0'Close Program'#0; hSMenu := MakeSubMenu(menuList, id4menu(m_MessBox,m_Second,m_Add2ListBox,88), id4menu(m_MessBox,m_Second,m_MessBox,m_Exit), hSubM1); {the MakeSubMenu function is limited to 8 clickable Items, but you can use the API menu functions to add more Items after you create it. You must get the sub-menu Handle (hSMenu) to use the API menu functions below} InsertMenu(hSMenu, 3, MF_BYPOSITION or MF_STRING, m_AddedItem, 'LOOK Added Item'); menuList := #251'Change Color Panel 1'#0'mMove Panel 2'#0'Exit'#0; hSubM1 := MakeSubMenu(menuList, id4menu(m_ColorP1,m_MoveP2,m_Exit), Zero); {the MakeSubMenu function can Only add ONE sub Menu Item, but more can be placed on that sub Menu with the InsertMenu function} InsertMenu(hSMenu, One, MF_BYPOSITION or MF_STRING or MF_POPUP, hSubM1, 'LOOK Added PopUp'); menuList := ''; { when MakeForm( ) is called the menu created above will automaticaly be the Form's Main Menu, so you must Create the menu BEFORE you call MakeForm} hForm1 := MakeForm(DEF, DEF, 500, 291, 'Use MakeApp', WS_TILEDWINDOW or WS_CLIPCHILDREN); if hForm1 = Zero then Exit; Result := True; MakeControls; // control creation procedure above end; initialization finalization DeleteObject(Font1); DeleteObject(FontP); end. |
This should give you some ideas about using the MakeApp Unit, so you can create your own "One Size Fits All" program creation unit, that has the code and constants that you frequently use for program, control, font, or brush creation. And you can even create more units with other common code, that you may use for a certain control or purpose, like a User-Draw control. NOTE - If you make several "Common Code" units and include them in your project, you will see the byte size of your executable increase. A "One Size Fits All" unit will add code that may NOT be needed because you have made the code to do many things. If your purpose is to have small and highly efficient programs, you may not want to use any "One Size Fits All" units. You can create your own units and then try to make some code that is reusable. |
Next in Code Container Series
The following page shows you how to make a code container unit that has graphic (non-windowed) controls
13b. Graphic Control Creation