It appears there are significant if not insurmountable obstacles to converting Visual Basic data bound grid control code (or the lack thereof) directly to PowerBASIC. Let me explain this in detail, and the workarounds. The key word in my first sentence above is 'directly'.
Here is the issue. One of the reasons Visual Basic was so popular was that it allowed for the first time novice programmers to accomplish really significant applications with almost no coding. One of the best examples of that were data bound grid controls. With these, a coder could drag a data control onto a Form, then a data bound grid control, and by just filling in a couple 'properties' in Visual Basic's 'Property Pane' such as the database path to connect to and the table desired, and with no code written at all create a usable app! Such an app would then transparently accomplish the following ...
1) Open a database and table;
2) Determine schematics of table such as number rows, columns, column names, data types, etc;
3) Configure grid to accept this data;
4) Retrieve data from database table and populate grid;
5) Persist user edits/changes in grid back to database and table
The code to accomplish the above is not trivial. And Visual Basic users did not have to deal with it. It was taken care of transparently by Visual Basic. Now it would stand to reason that since the components involved, i.e., data controls and data bound grid controls, are ActiveX Components with published interfaces, that it would be possible to translate this code on a line by line basis directly to PowerBASIC, because we have the capability in PowerBASIC to use ActiveX Controls. The problem appears to be the connection or interface between the grid control which displays data and the data control which negotiates with the connected data source. When using Visual Basic all one needs to do to make the connection is fill in the DataSource property of a grid control and it just works. Allowable DataSource names would be the name of a data control on the user's Form. But when looking at the interface names exported from a type library by either the PowerBASIC COM Browser or Jose Roca's TypeLib Browser, the Set DataSource method requires not a data control name but an IUnknown interface pointer. And neither Jose Roca or myself have been able to provide any which work. Worse, examining the *.idl file for these controls (Interface Definition Language) produced by OleView.exe indicates that the parameter is actually a DataSource* (an interface pointer), and these are part of non-creatable COM objects. And so far I've found no way to retrieve one and use it so as to make these things work. So near but yet so far! I've had no difficulty instantiating these objects with PowerBASIC; I just can't get them to speak to each other! You've probably heard the old adage "Close only counts in horseshoes and hand grenades!"
So the bottom line is that if you have Visual Basic code using any of these things and you wish to convert it to PowerBASIC, you are going to have to perform my five steps above yourself. Just like in the good old days before Visual Basic. If you just want to display data and not persist it back to the data source then you can get by with just the top four.
Now this situation raises all kinds of questions if you wish to translate such code to PowerBASIC. Let's take a look at my #1 above - "Open a database and table". Well, now you are going to have to decide which database technology or Api you are going to use. Any old VB code from before VB6 is going to be using ODBC (Open Database Connectivity) or more likely DAO (Data Access Objects). RDO is even a remote possibility. With VB6 we're probably talking DAO, ADO (ActiveX Data Objects) or ODBC. So your choices in PowerBASIC are SQL Tools by Perfect Sync Software if you want to purchase an ODBC Api, make direct ODBC function calls yourself which is free, develop your own Class wrapper around the ODBC Api like I've done, or use the PowerBASIC COM Browser to create includes which will work with DAO or ADO which are COM technologies. Also, Jose Roca has developed ODBC, ADO, and DAO wrappers which are excellent and are available here on this forum. And when you've finally made this choice of which database Api to use, you are going to have to write the code yourself to extract your data out of the database. PowerBASIC won't do it for you.
Now let's consider my #3 above - "Configure grid to accept this data". Well, which grid? The data bound grids are out of the picture I believe. Maybe someone can correct me if I'm wrong, but I believe they were designed specifically to accept their data from data controls, and we can't get these to work together as I've explained above. That's why I'm writing this. So you are going to have to come up with a grid control that you can use. There are choices. If you have the Professional or Enterprise Edition of Visual Basic 6 you have a license to use the MSFlexGrid ActiveX Control supplied with those editions. I'll provide code here showing how to use this grid to accomplish my five steps above. Jose Roca has already provided such code here and other places for every version of PowerBASIC since version 7, but I'll rehash that with an eye to conversions from Visual Basic and persisting edits back to the database.
But the MSFlexGrid is rather old, dating all the way back to 1998 or so, and it is for sure your typical bloat ware Microsoft product, and to make matters worse there is some miserable licensing code to deal with as well as other dependencies. So since you are going to have to deal with all this yourself from scratch, so to speak, you may wish to consider other grid controls, and there are a lot of choices. Around 2003 I purchased a grid control from a PowerBASIC vendor named the SIGrid. It really worked well for me, but I don't believe its available anymore. At the present time I'm aware of two PowerBASIC Forum members who market grid controls, and that would be James Klutho and Elias Montoya. Other PowerBASIC Forum members have provided grid code in the PowerBASIC Forums, and I've provided grid code here in Jose's Forum in both ActiveX Control and Custom Control form. After I've shown several different techniques of using the MSFlexGrid in terms of my five steps above, I'll demonstrate accomplishing the same with my grid code. And I'll use for an example connecting to some tables in the Biblio.mdb file supplied, I believe, with all versions of Visual Basic and likely Microsoft Access too. And maybe we can get James Klutho and Elias Montoya to provide examples using their grids.
The next issue to consider is include files. In working with ActiveX Controls, for example the MSFlexGrid described above, its easier to use Jose Roca's include set. What I've always done is create a \WinApiEx directory right under my PowerBASIC installation directory, and alongside the WinApi directory already there, and unpack Jose's includes to there. Its possible to use the PowerBASIC includes but sometimes there's some tweaking involved. You'll find that some interfaces and types haven't been defined, for example. Nonetheless, I'll provide one example using the PowerBASIC includes. If you aren't going to be using ActiveX Controls it likely won't matter.
Another somewhat related issue is the one of ActiveX Control Containers. If you use my ActiveX Grid Control you won't need one, or if you use a non-COM custom grid control you won't need one, but if you want to use Microsoft's MSFlexGrid Control you will definitely need one. And there are realistically three choices there. And I'll list these in no particular order of desirability. You will have to make the choice. First comes an ActiveX Control Container provided by Microsoft itself through an Active Template Library dll named Atl71.dll. There are some functions exported from this dll that provide ActiveX Control containment. What's that all about you ask?
When you put an ActiveX Control in the Visual Basic 'Toolbox' its actually loaded and running. These controls have two modes - a design time mode and a runtime mode. For example, when you place an ActiveX Control on your Visual Basic Form and use the resizing functionality of the IDE to drag the corners about to achieve the sizing you want, running code in the IDE is interacting with running code in the ActiveX Dll to make this all work. So the point to take home from this is that these controls were largely designed to work within an IDE designed for graphical design such as Visual Basic. It is for this reason that I'm throwing out the idea to you that if you are a new PowerBASIC user migrating away from Visual Basic then your interests might best be served by using other types of controls than ActiveX Controls. There are substitutes for at least some of Visual Basic's ActiveX Controls. As I've mentioned, grids are available elsewhere. The MS Calendar Common Control can be substituted for MSCAL.OCX. If the situation were such that you could make a line by line translation of Visual Basic code to PowerBASIC code, then I can see there is a good argument for using the same controls in PowerBASIC that exist in a Visual Basic Project. But if there are no substitutes in PowerBASIC for various Visual Basic functionality, and a good deal of actual code must be written in PowerBASIC to achieve what Visual Basic was auto-generating 'behind the scenes', so to speak, then it seems to me to make sense to use different controls from those used in Visual Basic.
I almost forgot where I was at. We were discussing ActiveX Control Containers. In addition to the one provided by ATL there is Jose Roca's OLE Container Control. The code is in OLECON.inc, and if you download Jose's Include file set you will have it. I believe it all involves around 5000 lines of code Jose has written just in OLECON.inc. Of course, that code relies on additional code in his includes.
And Dominic Mitchell has created an ActiveX Control Container as part of his Phoenix product. As of yet I don't have that but I'm mentioning it because it is no doubt another very good alternative. I intend to try it out soon myself.
What I'm going to do here is show how I would translate Visual Basic Data Bound Grid Control code to PowerBASIC. First I'll describe the Visual Basic code I'm translating, then show how to use the MSFlexGrid and my grid control to hold the data. I'll try to provide examples using the PowerBASIC includes and Jose Roca's includes although most of my emphasis will be using Jose's includes. Here is the Visual Basic 6 project I'll use for an example ...
1) Open Visual Basic 6 and create a new *.exe project. You can leave the names of the default Form file and project file as Form1.frm and Project1.vbp;
2) Go to the Project Main Menu item and select 'Components'. This will bring up the Components Dialog Box where you can add various ActiveX Controls to the project. Add these two components to your Project1...
Microsoft ADO Data Control 6.0 (SP6) (OLEDB) C:\Windows\SysWow64\MSADODC.OCX
Microsoft DataGrid Control 6.0 (SP6) (OLEDB) C:\Windows\SysWow64\MSDATGRD.OCX
There are check boxes to do that. What that will do is add icons to these two ActiveX Controls to you VB 'Toolbox'. Then drag instances of these to your Form1. Align the ADO Data Control about 95% of the full width of Form1 at the bottom and use the rest of the space for the grid. Make it nice and pretty. While you are at it make the Form1 two or three times bigger;
3) Then go to the 'Properties" Window. Select the ADO Data Control, and that will display the properties of the data control in that window. The default name VB would have given the data control is Adodc1. That's fine. Click on the 'ConnectionString' property, and that will bring up a tabbed dialog where VB will guide you through creating a connection string. Set the Provider to Microsoft Jet OLEDB 4.0 and set the database to the Biblio.mdb that ships with every edition of Visual Basic. On my machines I always accept the default installation path, and its located in C:\Program Files (x86)\Microsoft Visual Studio\VB98. Then set the 'CommandType' to 2 - adCmdTable. That tells the data control its source within the database will be a plain ordinary table.
4) Next click on the data grid. That will bring up its properties in the 'Properties' pane. Find the all important 'DataSource' property. Click on that and a drop down arrow will appear in the value field. By this time VB is smart enough to realize a data control is on the form and when you click that drop down arrow you'll see Adodc1, which you can select. Do that. That's it! Not one line of code written! You can run this project and after several seconds you should see a form with a grid on it containing all the data from the Titles Table of Biblio.mdb. I believe any edits you make will be automatically written back to Biblio.mdb. So let's see what's involved in translating this to PowerBASIC. We'll start real simple and basic at first. For this example we'll just try to get a working MSFlexGrid ActiveX Control on a Form. We'll just specify three columns named 'Column 1', 'Column 2', and 'Column 3'. We'll use the PowerBASIC COM Browser from PBWin 10 to generate the MSFlexGrid interface includes, and we'll use the PowerBASIC Win Api includes installed by default with the PowerBASIC installation. And we'll use Active Template Library (ATL) Control Containment. So you'll need preferably Atl71.dll to be somewhere in your path. I'm not sure exactly where you'll get that file if you don't have it. I can email it to you if you are having difficulties locating it. Also, before getting ahead of myself, let me state that you need to be a licensed user of Visual Basic 6 Professional or Enterprise Edition and that needs to be installed.
Which brings up another nasty issue. The MSFlexGrid.OCX ActiveX Control is what is known as a licensed control. If you have either of those editions of Visual Basic I mentioned above you are a licensed user of that control. The way Microsoft has this all set up is tricky in the usual Microsoft fashion. The computer on which either of those versions is installed has what is known as a 'Machine License'. When such a machine is used to code a project using the MSFlexGrid, if you aren't using Visual Basic but PowerBASIC, C++, or something else, you need to use object creation code that includes the Runtime License for the control, or when the executable is run on a different machine without a 'Machine License', the MSFlexGrid won't instantiate, even if it has been satisfactorily registered with RegSvr32. I suppose this is to prevent another developer from getting a 'free' copy of the control from an install of an app and using it like he/she paid for it. When you use Jose Roca's TypeLib Browser to generate includes for ActiveX Controls, there is an option to generate the license code and include it in the file. I don't believe the PowerBASIC COM Browser has that option, so here is a little utility you can use to get your license code. Ohhh! But there's a catch! While we can avoid using Jose's TypeLib Browser to get the license, and we can avoid using his OleCon.inc ActiveX Control Container, we still can't leave Jose out of the picture (not that we would want to - I'm just trying to illustrate the pure stock PB way of doing it), for the code below requires the definition of the IClassFactory2 Interface, and unless you want to translate it from the IDL (Interface Definition Language) file yourself, you'll need Jose's includes to run this program! ...
#Compile Exe
#Dim All
#Include "Windows.inc"
#Include Once "Ocidl.inc"
$CLSID_MSFlexGrid = GUID$("{6262D3A0-531B-11CF-91F6-C2863C385E30}")
Declare Function DllGetClassObjectImpl(Byref Clsid As Guid, Byref iid As Guid, Byref pCF As IUnknown) As Long
Function PBMain() As Long
Local pClassFactory As IClassFactory2
Local pDllGetClassObject As Dword
Local strLicense As WString
Local lic as LICINFO
Local hDll As Dword
Local hr As Long
hDll=LoadLibrary("C:\Windows\SysWOW64\MSFlxGrd.ocx")
If hDll Then
pDllGetClassObject=GetProcAddress(hDll,"DllGetClassObject")
If pDllGetClassObject Then
Call Dword pDllGetClassObject Using DllGetClassObjectImpl($CLSID_MSFlexGrid, $IID_IClassFactory2, pClassFactory) To hr
If SUCCEEDED(hr) Then
hr=pClassFactory.GetLicInfo(lic)
If SUCCEEDED(hr) Then
If lic.fRuntimeKeyAvail And lic.fLicVerified Then
hr=pClassFactory.RequestLicKey(0, strLicense)
If SUCCEEDED(hr) Then
Con.Print "strLicense = " strLicense
End If
End If
End If
Set pClassFactory = Nothing
End If
End If
Call FreeLibrary(hDll)
End If
Con.Waitkey$
PBMain=0
End Function
And its a Console Compiler 6 program. If you don't have the Console Compiler print the outputs to a text file, e.g., Print #1, "strLicense = " strLicense. Here is the output on my computer ...
strLicense = 72E67120-5959-11cf-91F6-C2863C385E30
So if you just output it to a Message Box you are going to have to copy that correctly without mistakes. Its a GUID.
Next step is to open the PowerBASIC COM Browser and look for "Microsoft FlexGrid Control 6.0". Double click on that and the interface definitions will be created for you. Just a warning! With mine I had to change about a half dozen items, specifically, there was a method parameter named data that conflicted with a PowerBASIC reserved word, and several instances of the same problem with a 'Shift' keyword. I changed them like so ...
Data Changed To GridData
Shift Changed to iShift
I'll provide my include below, but if you generate yours from the PowerBASIC COM Browser you might run into those minor difficulties. If you are new to PowerBASIC and are not familiar with such issues then I suppose the problem isn't minor to you. Without further ado, here is MSFlexGrid1.bas ...
continued....
'MSFlexGrid1.bas ' Creates an instance of the MSFlexGrid
#Compile Exe "MSFlexGrid1" ' ActiveX Control on a Form. Compiles
%UNICODE = 1 ' with PBWin 10. Uses wide characters
#Include "Windows.inc" ' throughout. Requires Atl71.dll to be
#Include "MSFlexGrid.inc" ' in your PATH.
$ATL_DLLNAME = "Atl71.dll"
%ID_CONTAINER = 2000
Declare Function AtlAxWinInit Lib $ATL_DLLNAME Alias "AtlAxWinInit" () AS LONG
Declare Function AtlAxCreateControlLic Lib $ATL_DLLNAME Alias "AtlAxCreateControlLic" _
( _
Byref lpszName As WStringz, _
Byval hWnd As Dword, _
Byval pStream As IUnknown, _ ' This is actually an IStream
Byref ppUnkContainer As IUnknown, _
Byval bstrLic As WString _
) As Long
Declare Function AtlAxGetControl Lib $ATL_DLLNAME Alias "AtlAxGetControl" _
( _
Byval hWnd As Dword, _
Byref pp As IUnknown _
) As Long
Macro CObj(pUnk, dwAddr) = Poke Dword, Varptr(pUnk), dwAddr
Type WndEventArgs
wParam As Long
lParam As Long
hWnd As Dword
hInst As Dword
End Type
Sub GridSetup(Byref pGrid As IMSFlexGrid)
pGrid.FontName = "Times New Roman"
pGrid.FontSize = 10
pGrid.Cols = 4
pGrid.Rows = 20
pGrid.ColWidth(0) = 200
pGrid.ColWidth(1) = 1220
pGrid.ColWidth(2) = 1220
pGrid.ColWidth(3) = 1220
pGrid.Col = 1
pGrid.Row = 0
pGrid.Text = "Column 1"
pGrid.Col = 2
pGrid.Row = 0
pGrid.Text = "Column 2"
pGrid.Col = 3
pGrid.Row = 0
pGrid.Text = "Column 3"
End Sub
Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long ' This procedure is exactly equivalent to Form_Load() in Visual Basic.
Local pStream,ppUnkContainer,pUnkGrid As IUnknown ' 1st thing we do is retrieve the HINSTANCE from the CREATESTRUCT UDT.
Local lpCreateStruct As CREATESTRUCT Ptr ' Next create a 'label' (static) control to 'contain' the grid. Then
Local pEvents As DMSFlexGridEvents ' pass in the Program ID and License to AtlAxCreateControlLic(). This
Local pFlexGrid As IMSFlexGrid ' will give us the IUnknown of the Control Container. Next we create
Local pDispGrid As IDispatch ' an instance of the Event or Sink Class "Class_DMSFlexGridEvents".
Local szProgId As Wstringz*32 ' The definition and implementation of this class is in the MSFlexGrid
Local strLicense As WString ' include file. Then I store the interface pointer pEvents in the
Local hContainer As Dword ' Window Class structure of "OCX Test" object at WNDCLASS::cbWndExtra
Local hr As Long ' memory at offset 4. Then we use AtlAxGetControl() from Atl71.dll to
' get the IUnknown of the grid itself. We AddRef() that so PowerBASIC's
lpCreateStruct=Wea.lParam : Wea.hInst=@lpCreateStruct.hInstance ' stack variable clean up code won't Release() the object at...
hr=AtlAxWinInit()
If SUCCEEDED(hr) Then
hContainer=CreateWindowEx(0,"static","",%WS_CHILD OR %WS_VISIBLE,10,10,280,250,Wea.hWnd,%ID_CONTAINER,Wea.hInst,Byval %NULL)
szProgId = "MSFlexGridLib.MSFlexGrid"
strLicense = "72E67120-5959-11cf-91F6-C2863C385E30" ' you need your license here - not mine!
hr=AtlAxCreateControlLic(szProgId,hContainer,pStream,ppUnkContainer,strLicense)
If SUCCEEDED(hr) Then
pEvents=Class "Class_DMSFlexGridEvents" ' procedure termination. Note all my variables are locals - no globals
Call SetWindowLong(Wea.hWnd,4,Objptr(pEvents)) ' in this program. Then I store that pointer at offset zero in the
hr = AtlAxGetControl(hContainer, pUnkGrid) ' WNDCLASSEX::cbWndExtra bytes. To turn on event handling from the
If SUCCEEDED(hr) Then ' grid we use PowerBASIC's 'Events From' ... Call syntax. I put
pUnkGrid.AddRef() ' various code to configure the grid in my GridSetup() procedure. That
Call SetWindowLong(Wea.hWnd,0,Objptr(pUnkGrid)) ' requires an IMSFlexGrid pointer, so I had to QueryInterface() for
pDispGrid=pUnkGrid ' that using pFlexGrid=pUnkGrid syntax (PB calls QueryInterface(). And
Events From pDispGrid Call pEvents ' the Events code is a dispinterface only (not dual), and requires an
pFlexGrid=pUnkGrid ' IDispatch pointer - pDispGrid.
Call GridSetup(pFlexGrid)
End If
End If
End If
fnWndProc_OnCreate=0
End Function
Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long ' This is Form_Unload() or Form_Terminate() in Visual Basic - not sure
Local pEvents As DMSFlexGridEvents ' which. You can't prevent destruction of the Form at this point. Its
Local pGrid As IUnknown ' on the way out and 'nothin's gonna bring it back. I've got a reference
Local pObj As Dword ' count of +1 on the grid though that I've got to cancel out if I want
' the grid released though (that's why it wasn't destroyed when
pObj=GetWindowLong(Wea.hWnd,4) ' fnWndProc_OnCreate() exited - that +1 count). So here I retrieve my
CObj(pEvents,pObj) ' stored pointer to the Events interface = pEvents, and terminate that
If IsObject(pEvents) Then ' connection. Next cause a Release call on the grid itself by setting
Events End pEvents ' the pointer to 'Nothing'. Note one needs to do some chicanery here
Set pEvents=Nothing ' to outwit the compiler. It won't allow you to directly install values
End If ' into interface pointers or read them. My CObj macro uses Poke Dword
pObj=GetWindowLong(Wea.hWnd,0) ' to slip (poke) the number in when it isan't looking. Finally,
If pObj Then ' PostQuitMessage() ends the message pump down in WinMain() and the
CObj(pGrid,pObj) ' program ends.
Set pGrid=Nothing
End If
Call PostQuitMessage(0)
fnWndProc_OnDestroy=0
End Function
Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
Local Wea As WndEventArgs
Select Case As Long wMsg
Case %WM_CREATE
Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
fnWndProc=fnWndProc_OnCreate(Wea)
Exit Function
Case %WM_DESTROY
Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
fnWndProc=fnWndProc_OnDestroy(Wea)
Exit Function
End Select
fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function
Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
Local winclass As WndClassEx
Local szAppName As WStringz*16
Local Msg As tagMsg
Local hWnd As Dword
szAppName="OCX Test" : winclass.cbSize=SizeOf(winclass)
winclass.lpfnWndProc=CodePtr(fnWndProc) : winclass.cbClsExtra=0
winclass.cbWndExtra=8 : winclass.hInstance=hIns
winclass.hIcon=LoadIcon(%NULL,ByVal %IDI_APPLICATION) : winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)
winclass.hbrBackground=%COLOR_BTNFACE+1 : winclass.lpszClassName=VarPtr(szAppName)
Call RegisterClassEx(winclass)
hWnd=CreateWindowEx(0,szAppName,"Try MSFlexGrid",%WS_OVERLAPPEDWINDOW Xor %WS_MAXIMIZEBOX,200,100,310,310,0,0,hIns,ByVal 0)
Call ShowWindow(hWnd,iShow)
While GetMessage(Msg,%NULL,0,0)
Call TranslateMessage(Msg)
Call DispatchMessage(Msg)
Wend
Function=msg.wParam
End Function
I don't consider the above to be an exceedingly large Win32 Api SDK style program for creating something as sophisticated as an ActiveX Grid Control. But we haven't looked at the Auto-Generated MSFlexGrid.inc file yet mostly generated by the PowerBASIC COM Browser. That's a good bit bigger, but simply because the MSFlexGrid has a lot of methods in its interfaces ...
' Generated by: PowerBASIC COM Browser v.2.00.0086
' Date & Time : 9/15/2014 at 3:07 PM
' Options:
' Always use an Interface Prefix : Off
' Interface Prefix : grd
' Prefix ProgIDs, ClassIDs... : Off
' Use ANSI Strings : Off
' Use Singular Enumerations : On
' Generate Dispatch Interfaces : Off
' Include Parameter Names : On
' Use Property Get/Set statements: On
' ------------------------------------------------
' Library Name: MSFlexGridLib
' Library File: C:\Windows\SysWow64\MSFLXGRD.OCX
' Description : Microsoft FlexGrid Control 6.0 (SP6)
' Help File : C:\Windows\HELP\MSHFlx98.chm
' Help Context : 0
' GUID : {5E9E78A0-531B-11CF-91F6-C2863C385E30}
' LCID : 0
' Version : 1.0
' Version Dependent ProgIDs
$PROGID_MSFlexGrid1 = "MSFlexGridLib.MSFlexGrid.1"
' Version Independent ProgIDs
$PROGID_MSFlexGrid = "MSFlexGridLib.MSFlexGrid"
' Class Identifiers
$CLSID_DataObject = GUID$("{2334D2B2-713E-11CF-8AE5-00AA00C00905}")
$CLSID_DataObjectFiles = GUID$("{2334D2B4-713E-11CF-8AE5-00AA00C00905}")
$CLSID_MSFlexGrid = GUID$("{6262D3A0-531B-11CF-91F6-C2863C385E30}")
$CLSID_Event_DMSFlexGridEvents = GUID$("{8BAAFAFB-74CA-4062-A7D8-146C6EEE03C3}")
' Interface Identifiers
$IID_IVBDataObject = GUID$("{2334D2B1-713E-11CF-8AE5-00AA00C00905}")
$IID_IVBDataObjectFiles = GUID$("{2334D2B3-713E-11CF-8AE5-00AA00C00905}")
$IID_IRowCursor = GUID$("{9F6AA700-D188-11CD-AD48-00AA003C9CB6}")
$IID_IMSFlexGrid = GUID$("{5F4DF280-531B-11CF-91F6-C2863C385E30}")
$IID_DMSFlexGridEvents = GUID$("{609602E0-531B-11CF-91F6-C2863C385E30}")
Enum OLEDragConstants Singular
flexOLEDragManual = 0
flexOLEDragAutomatic = 1
End Enum
Enum OLEDropConstants Singular
flexOLEDropNone = 0
flexOLEDropManual = 1
End Enum
Enum DragOverConstants Singular
flexEnter = 0
flexLeave = 1
flexOver = 2
End Enum
Enum ClipBoardConstants Singular
flexCFText = 1
flexCFBitmap = 2
flexCFMetafile = 3
flexCFDIB = 8
flexCFPalette = 9
flexCFEMetafile = 14
flexCFFiles = 15
flexCFRTF = -16639
End Enum
Enum OLEDropEffectConstants Singular
flexOLEDropEffectNone = 0
flexOLEDropEffectCopy = 1
flexOLEDropEffectMove = 2
flexOLEDropEffectScroll = -2147483648
End Enum
Enum ErrorConstants Singular
flexerrIllegaFunctionCall = 5
flexerrObjIllegalUse = 425
flexerrClipInvalidFormat = 461
flexerrDataObjectLocked = 672
flexerrExpectedAnArgument = 673
flexerrRecursiveOLEDrag = 674
flexerrUserFormatNotBinArray = 675
flexerrDataNotSetForFormat = 676
flexerrUnknownError = 600
flexerrSubscript = 381
flexerrBadValue = 380
flexerrGetNotSupported = 394
flexerrSetNotPermitted = 387
flexerrOutOfMemory = 7
flexerrVB30000 = 30000
flexerrVB30001 = 30001
flexerrVB30002 = 30002
flexerrVB30004 = 30004
flexerrVB30005 = 30005
flexerrVB30006 = 30006
flexerrVB30008 = 30008
flexerrVB30009 = 30009
flexerrVB30010 = 30010
flexerrVB30011 = 30011
flexerrVB30013 = 30013
flexerrVB30014 = 30014
flexerrVB30015 = 30015
flexerrVB30016 = 30016
flexerrVB30017 = 30017
End Enum
Enum AppearanceSettings Singular
flexFlat = 0
flex3D = 1
End Enum
Enum BorderStyleSettings Singular
flexBorderNone = 0
flexBorderSingle = 1
End Enum
Enum FocusRectSettings Singular
flexFocusNone = 0
flexFocusLight = 1
flexFocusHeavy = 2
End Enum
Enum HighLightSettings Singular
flexHighlightNever = 0
flexHighlightAlways = 1
flexHighlightWithFocus = 2
End Enum
Enum ScrollBarsSettings Singular
flexScrollBarNone = 0
flexScrollBarHorizontal = 1
flexScrollBarVertical = 2
flexScrollBarBoth = 3
End Enum
Enum TextStyleSettings Singular
flexTextFlat = 0
flexTextRaised = 1
flexTextInset = 2
flexTextRaisedLight = 3
flexTextInsetLight = 4
End Enum
Enum FillStyleSettings Singular
flexFillSingle = 0
flexFillRepeat = 1
End Enum
Enum GridLineSettings Singular
flexGridNone = 0
flexGridFlat = 1
flexGridInset = 2
flexGridRaised = 3
End Enum
Enum SelectionModeSettings Singular
flexSelectionFree = 0
flexSelectionByRow = 1
flexSelectionByColumn = 2
End Enum
Enum MergeCellsSettings Singular
flexMergeNever = 0
flexMergeFree = 1
flexMergeRestrictRows = 2
flexMergeRestrictColumns = 3
flexMergeRestrictAll = 4
End Enum
Enum PictureTypeSettings Singular
flexPictureColor = 0
flexPictureMonochrome = 1
End Enum
Enum AllowUserResizeSettings Singular
flexResizeNone = 0
flexResizeColumns = 1
flexResizeRows = 2
flexResizeBoth = 3
End Enum
Enum MousePointerSettings Singular
flexDefault = 0
flexArrow = 1
flexCross = 2
flexIBeam = 3
flexIcon = 4
flexSize = 5
flexSizeNESW = 6
flexSizeNS = 7
flexSizeNWSE = 8
flexSizeEW = 9
flexUpArrow = 10
flexHourglass = 11
flexNoDrop = 12
flexArrowHourGlass = 13
flexArrowQuestion = 14
flexSizeAll = 15
flexCustom = 99
End Enum
Enum SortSettings Singular
flexSortNone = 0
flexSortGenericAscending = 1
flexSortGenericDescending = 2
flexSortNumericAscending = 3
flexSortNumericDescending = 4
flexSortStringNoCaseAscending = 5
flexSortStringNoCaseDescending = 6
flexSortStringAscending = 7
flexSortStringDescending = 8
End Enum
Enum AlignmentSettings Singular
flexAlignLeftTop = 0
flexAlignLeftCenter = 1
flexAlignLeftBottom = 2
flexAlignCenterTop = 3
flexAlignCenterCenter = 4
flexAlignCenterBottom = 5
flexAlignRightTop = 6
flexAlignRightCenter = 7
flexAlignRightBottom = 8
flexAlignGeneral = 9
End Enum
' Interface Name : IVBDataObject
' Class Name : DataObject
' ClassID : $CLSID_DataObject
' This Interface cannot be created directly it can only
' be returned by a Method or Property in this library.
Interface IVBDataObject $IID_IVBDataObject
Inherit IDispatch
Method Clear <1> ()
Method GetData <2> (Byval sFormat As Integer) As Variant
Method GetFormat <3> (Byval sFormat As Integer) As Integer
Method SetData <4> (Opt Byval vValue As Variant, Opt Byval vFormat As Variant)
Property Get Files <5> () As IVBDataObjectFiles
End Interface
' Interface Name : IVBDataObjectFiles
' Class Name : DataObjectFiles
' ClassID : $CLSID_DataObjectFiles
' This Interface cannot be created directly it can only
' be returned by a Method or Property in this library.
Interface IVBDataObjectFiles $IID_IVBDataObjectFiles
Inherit IDispatch
Property Get Item <0> (ByVal lIndex As Long) As WString
Property Get Count <1> () As Long
Method Add <2> (Byval bstrFilename As WString, Opt Byval vIndex As Variant)
Method Clear <3> ()
Method Remove <4> (Byval vIndex As Variant)
Method Meth__NewEnum <-4> () As IUnknown
End Interface
' Interface Name : IRowCursor
' This Interface cannot be created directly it can only
' be returned by a Method or Property in this library.
Interface IRowCursor $IID_IRowCursor
Inherit IDispatch
End Interface
' Interface Name : IMSFlexGrid
' Description : Dispatch interface for Microsoft FlexGrid Control
' Class Name : MSFlexGrid
' ClassID : $CLSID_MSFlexGrid
' ProgID : $PROGID_MSFlexGrid
' Version ProgID : $PROGID_MSFlexGrid1
Interface IMSFlexGrid $IID_IMSFlexGrid
Inherit IDispatch
Property Get Rows <4> () As Long
Property Set Rows <4> (ByVal Rows As Long)
Property Get Cols <5> () As Long
Property Set Cols <5> (ByVal Cols As Long)
Property Get FixedRows <6> () As Long
Property Set FixedRows <6> (ByVal FixedRows As Long)
Property Get FixedCols <7> () As Long
Property Set FixedCols <7> (ByVal FixedCols As Long)
Property Get Version <1> () As Integer
Property Get FormatString <2> () As WString
Property Set FormatString <2> (ByVal FormatString As WString)
Property Get TopRow <8> () As Long
Property Set TopRow <8> (ByVal TopRow As Long)
Property Get LeftCol <9> () As Long
Property Set LeftCol <9> (ByVal LeftCol As Long)
Property Get Row <10> () As Long
Property Set Row <10> (ByVal Row As Long)
Property Get Col <11> () As Long
Property Set Col <11> (ByVal Col As Long)
Property Get RowSel <12> () As Long
Property Set RowSel <12> (ByVal RowSel As Long)
Property Get ColSel <13> () As Long
Property Set ColSel <13> (ByVal ColSel As Long)
Property Get Text <0> () As WString
Property Set Text <0> (ByVal Text As WString)
Property Get BackColor <-501> () As DWord
Property Set BackColor <-501> (ByVal BackColor As DWord)
Property Get ForeColor <-513> () As DWord
Property Set ForeColor <-513> (ByVal ForeColor As DWord)
Property Get BackColorFixed <14> () As DWord
Property Set BackColorFixed <14> (ByVal BackColorFixed As DWord)
Property Get ForeColorFixed <15> () As DWord
Property Set ForeColorFixed <15> (ByVal ForeColorFixed As DWord)
Property Get BackColorSel <16> () As DWord
Property Set BackColorSel <16> (ByVal BackColorSel As DWord)
Property Get ForeColorSel <17> () As DWord
Property Set ForeColorSel <17> (ByVal ForeColorSel As DWord)
Property Get BackColorBkg <18> () As DWord
Property Set BackColorBkg <18> (ByVal BackColorBkg As DWord)
Property Get WordWrap <19> () As Integer
Property Set WordWrap <19> (ByVal WordWrap As Integer)
Property Get Font <-512> () As IDispatch
Property Set PutRef_Font <-512> (ByVal PB_Font As IDispatch)
Property Get FontWidth <84> () As Single
Property Set FontWidth <84> (ByVal FontWidth As Single)
Property Get CellFontName <77> () As WString
Property Set CellFontName <77> (ByVal CellFontName As WString)
Property Get CellFontSize <78> () As Single
Property Set CellFontSize <78> (ByVal CellFontSize As Single)
Property Get CellFontBold <79> () As Integer
Property Set CellFontBold <79> (ByVal CellFontBold As Integer)
Property Get CellFontItalic <80> () As Integer
Property Set CellFontItalic <80> (ByVal CellFontItalic As Integer)
Property Get CellFontUnderline <81> () As Integer
Property Set CellFontUnderline <81> (ByVal CellFontUnderline As Integer)
Property Get CellFontStrikeThrough <82> () As Integer
Property Set CellFontStrikeThrough <82> (ByVal CellFontStrikeThrough As Integer)
Property Get CellFontWidth <83> () As Single
Property Set CellFontWidth <83> (ByVal CellFontWidth As Single)
Property Get TextStyle <20> () As Long
Property Set TextStyle <20> (ByVal TextStyle As Long)
Property Get TextStyleFixed <21> () As Long
Property Set TextStyleFixed <21> (ByVal TextStyleFixed As Long)
Property Get ScrollTrack <22> () As Integer
Property Set ScrollTrack <22> (ByVal ScrollTrack As Integer)
Property Get FocusRect <23> () As Long
Property Set FocusRect <23> (ByVal FocusRect As Long)
Property Get HighLight <24> () As Long
Property Set HighLight <24> (ByVal HighLight As Long)
Property Get Redraw <25> () As Integer
Property Set Redraw <25> (ByVal PB_Redraw As Integer)
Property Get ScrollBars <26> () As Long
Property Set ScrollBars <26> (ByVal ScrollBars As Long)
Property Get MouseRow <27> () As Long
Property Get MouseCol <28> () As Long
Property Get CellLeft <29> () As Long
Property Get CellTop <30> () As Long
Property Get CellWidth <31> () As Long
Property Get CellHeight <32> () As Long
Property Get RowHeightMin <33> () As Long
Property Set RowHeightMin <33> (ByVal RowHeightMin As Long)
Property Get FillStyle <-511> () As Long
Property Set FillStyle <-511> (ByVal FillStyle As Long)
Property Get GridLines <34> () As Long
Property Set GridLines <34> (ByVal GridLines As Long)
Property Get GridLinesFixed <35> () As Long
Property Set GridLinesFixed <35> (ByVal GridLinesFixed As Long)
Property Get GridColor <36> () As DWord
Property Set GridColor <36> (ByVal GridColor As DWord)
Property Get GridColorFixed <37> () As DWord
Property Set GridColorFixed <37> (ByVal GridColorFixed As DWord)
Property Get CellBackColor <38> () As DWord
Property Set CellBackColor <38> (ByVal CellBackColor As DWord)
Property Get CellForeColor <39> () As DWord
Property Set CellForeColor <39> (ByVal CellForeColor As DWord)
Property Get CellAlignment <40> () As Integer
Property Set CellAlignment <40> (ByVal CellAlignment As Integer)
Property Get CellTextStyle <41> () As Long
Property Set CellTextStyle <41> (ByVal CellTextStyle As Long)
Property Get CellPictureAlignment <43> () As Integer
Property Set CellPictureAlignment <43> (ByVal CellPictureAlignment As Integer)
Property Get Clip <45> () As WString
Property Set Clip <45> (ByVal Clip As WString)
Property Set Sort <46> (ByVal Rhs As Integer)
Property Get SelectionMode <47> () As Long
Property Set SelectionMode <47> (ByVal SelectionMode As Long)
Property Get MergeCells <48> () As Long
Property Set MergeCells <48> (ByVal MergeCells As Long)
Property Get AllowBigSelection <51> () As Integer
Property Set AllowBigSelection <51> (ByVal AllowBigSelection As Integer)
Property Get AllowUserResizing <52> () As Long
Property Set AllowUserResizing <52> (ByVal AllowUserResizing As Long)
Property Get BorderStyle <-504> () As Long
Property Set BorderStyle <-504> (ByVal BorderStyle As Long)
Property Get hWnd <-515> () As Long
Property Get Enabled <-514> () As Integer
Property Set Enabled <-514> (ByVal Enabled As Integer)
Property Get Appearance <-520> () As Long
Property Set Appearance <-520> (ByVal Appearance As Long)
Property Get MousePointer <53> () As Long
Property Set MousePointer <53> (ByVal MousePointer As Long)
Property Get MouseIcon <54> () As IDispatch
Property Set PutRef_MouseIcon <54> (ByVal MouseIcon As IDispatch)
Property Get PictureType <50> () As Long
Property Set PictureType <50> (ByVal PictureType As Long)
Property Get Picture <49> () As IDispatch
Property Get CellPicture <42> () As IDispatch
Property Set PutRef_CellPicture <42> (ByVal CellPicture As IDispatch)
Method AboutBox <-552> ()
Property Get TextArray <55> (ByVal index As Long) As WString
Property Set TextArray <55> (ByVal index As Long, ByVal TextArray As WString)
Property Get ColAlignment <56> (ByVal index As Long) As Integer
Property Set ColAlignment <56> (ByVal index As Long, ByVal ColAlignment As Integer)
Property Get ColWidth <57> (ByVal index As Long) As Long
Property Set ColWidth <57> (ByVal index As Long, ByVal ColWidth As Long)
Property Get RowHeight <58> (ByVal index As Long) As Long
Property Set RowHeight <58> (ByVal index As Long, ByVal RowHeight As Long)
Property Get MergeRow <59> (ByVal index As Long) As Integer
Property Set MergeRow <59> (ByVal index As Long, ByVal MergeRow As Integer)
Property Get MergeCol <60> (ByVal index As Long) As Integer
Property Set MergeCol <60> (ByVal index As Long, ByVal MergeCol As Integer)
Property Set RowPosition <61> (ByVal index As Long, ByVal Rhs As Long)
Property Set ColPosition <62> (ByVal index As Long, ByVal Rhs As Long)
Property Get RowData <63> (ByVal index As Long) As Long
Property Set RowData <63> (ByVal index As Long, ByVal RowData As Long)
Property Get ColData <64> (ByVal index As Long) As Long
Property Set ColData <64> (ByVal index As Long, ByVal ColData As Long)
Property Get TextMatrix <65> (ByVal Row As Long, ByVal Col As Long) As WString
Property Set TextMatrix <65> (ByVal Row As Long, ByVal Col As Long, ByVal TextMatrix As WString)
Method AddItem <66> (Byval Item As WString, Opt Byval index As Variant)
Method RemoveItem <67> (Byval index As Long)
Method Clear <68> ()
Method Refresh <-550> ()
Property Get DataSource <76> () As IRowCursor
Property Set DataSource <76> (ByVal DataSource As IRowCursor)
Property Get RowIsVisible <85> (ByVal index As Long) As Integer
Property Get ColIsVisible <86> (ByVal index As Long) As Integer
Property Get RowPos <87> (ByVal index As Long) As Long
Property Get ColPos <88> (ByVal index As Long) As Long
Property Get GridLineWidth <89> () As Integer
Property Set GridLineWidth <89> (ByVal GridLineWidth As Integer)
Property Get FixedAlignment <90> (ByVal index As Long) As Integer
Property Set FixedAlignment <90> (ByVal index As Long, ByVal FixedAlignment As Integer)
Property Get FontName <91> () As WString
Property Set FontName <91> (ByVal FontName As WString)
Property Get FontSize <92> () As Single
Property Set FontSize <92> (ByVal FontSize As Single)
Property Get FontBold <93> () As Integer
Property Set FontBold <93> (ByVal FontBold As Integer)
Property Get FontItalic <94> () As Integer
Property Set FontItalic <94> (ByVal FontItalic As Integer)
Property Get FontStrikethru <95> () As Integer
Property Set FontStrikethru <95> (ByVal FontStrikethru As Integer)
Property Get FontUnderline <96> () As Integer
Property Set FontUnderline <96> (ByVal FontUnderline As Integer)
Property Get RightToLeft <-611> () As Integer
Property Set RightToLeft <-611> (ByVal RightToLeft As Integer)
Property Get OLEDropMode <1551> () As Long
Property Set OLEDropMode <1551> (ByVal psOLEDropMode As Long)
Method OLEDrag <1552> ()
End Interface
' Interface Name : DMSFlexGridEvents
' Description : Event interface for Microsoft FlexGrid Control
' ClassID : $CLSID_Event_DMSFlexGridEvents
' ProgID : $PROGID_MSFlexGrid
' Version ProgID : $PROGID_MSFlexGrid1
Class Class_DMSFlexGridEvents $CLSID_Event_DMSFlexGridEvents As Event
Interface DMSFlexGridEvents $IID_DMSFlexGridEvents
Inherit IDispatch
Method Click <-600> ()
' Insert your code here
End Method
Method KeyDown <-602> (ByRef KeyCode As Integer, ByVal PB_Shift As Integer)
' Insert your code here
End Method
Method DblClick <-601> ()
MsgBox("You Double Clicked In The Grid!")
End Method
Method KeyPress <-603> (ByRef KeyAscii As Integer)
MsgBox("You Pressed The " & Chr$(KeyAscii) & " Key!")
End Method
Method KeyUp <-604> (ByRef KeyCode As Integer, ByVal PB_Shift As Integer)
' Insert your code here
End Method
Method MouseDown <-605> (ByVal Button As Integer, ByVal PB_Shift As Integer, ByVal x As Long, ByVal y As Long)
' Insert your code here
End Method
Method MouseMove <-606> (ByVal Button As Integer, ByVal PB_Shift As Integer, ByVal x As Long, ByVal y As Long)
' Insert your code here
End Method
Method MouseUp <-607> (ByVal Button As Integer, ByVal PB_Shift As Integer, ByVal x As Long, ByVal y As Long)
' Insert your code here
End Method
Method SelChange <69> ()
' Insert your code here
End Method
Method RowColChange <70> ()
' Insert your code here
End Method
Method EnterCell <71> ()
' Insert your code here
End Method
Method LeaveCell <72> ()
' Insert your code here
End Method
Method Scroll <73> ()
' Insert your code here
End Method
Method Compare <74> (ByVal Row1 As Long, ByVal Row2 As Long, ByRef Cmp As Integer)
' Insert your code here
End Method
Method OLEStartDrag <1550> (ByRef InOut GridData As IDispatch, ByRef InOut AllowedEffects As Long)
' Insert your code here
End Method
Method OLEGiveFeedback <1551> (ByRef InOut Effect As Long, ByRef InOut DefaultCursors As Integer)
' Insert your code here
End Method
Method OLESetData <1552> (ByRef InOut GridData As IDispatch, ByRef InOut DataFormat As Integer)
' Insert your code here
End Method
Method OLECompleteDrag <1553> (ByRef InOut Effect As Long)
' Insert your code here
End Method
Method OLEDragOver <1554> (ByRef InOut GridData As IDispatch, ByRef InOut Effect As Long, ByRef InOut Button As Integer, ByRef InOut iShift As Integer, ByRef InOut x As Single, ByRef InOut y As Single, ByRef InOut _
State As Integer)
' Insert your code here
End Method
Method OLEDragDrop <1555> (ByRef InOut GridData As IDispatch, ByRef InOut Effect As Long, ByRef InOut Button As Integer, ByRef InOut iShift As Integer, ByRef InOut x As Single, ByRef InOut y As Single)
' Insert your code here
End Method
End Interface
End Class
To get the above program working for you all you need to do - so far as I know, is use your license key on your 'Machine Licensed' Workstation instead of mine up in fnWndProc_OnCreate(), have the MSFlxGrd.OCX ActiveX Control registered on your system, and have Atl71.dll somewhere in your path. If you've done that, I expect an executable produced by you should be able to be run on another machine if MSFlxGrd is copied and registered there. Here would be the dependencies for the above program ...
MSFlexGrid1.exe 22 K
Atl71.dll 87 K
MSFlxGrd.ocx 255 K
========================
364 K
... continued...
In terms of alterations made by me to the include file above, other than the 'data' and Shift' reserved keyword issue previously mentioned, I added a MsgBox to the KepPress() and DblClick() Event Procedures so you can see that they are working.
The last thing I'll mention about the above code is that there are three declares up top. These are for Atl71.dll. I changed an argument in AtlAxCreateControlLic(). Its the 3rd one. That's actually supposed to be 'pStream As IStream', not pStream As IUnknown. But I wanted this to work with the PowerBASIC includes and the IStream interface isn't defined there. The argument can be left NULL in the function if it isn't used, so changing it from IStream to IUnknown was workable in this instance. Like with the IClassFactory2 interface, it is correctly defined in Jose Roca's includes. Which is our next stop!
This next version of the above program is exactly the same as the last in terms of what it looks like at runtime, but its coding is considerably different. Jose Roca coded an Active X Control Container in PowerBASIC implemented in "OleCon.inc". With this, you won't need Atl71.dll or the declares for those functions. Download Jose's extended include file set and you'll have it. I include the files in a directory next to my PowerBASIC installation's WinApi directory, and I name the directory the files are in WinApiEx. In the PowerBASIC IDE go to ...
Window >>>> Options ...
...and when the tabbed dialog comes up click on the 'Compiler' tab. Delete the directory there and use the choose folder dialog to highlight the folder in which you unpacked Jose's includes. Then you are ready to go. You can easily undo this when you want to return to the PowerBASIC includes. With Jose's coding, you can forego all those strange Atl functions, and simply create the control with a call to CreateWindowEx() ...
'MSFlexGrid2.bas
#Compile Exe "MSFlexGrid2"
%UNICODE = 1
#If %Def(%UNICODE)
Macro ZStr = WStringz
Macro BStr = WString
%SIZEOF_CHAR = 2
#Else
Macro ZStr = Asciiz
Macro BStr = String
%SIZEOF_CHAR = 1
#EndIf
#Include "Windows.inc"
#Include "OleCon.inc"
#Include Once "MSFlexGridLib2.inc"
#Include Once "MSFlexGridLibEvents2.inc"
%ID_CONTAINER = 2000
Macro CObj (pUnk, dwAddr) = Poke Dword, Varptr(pUnk), dwAddr
Type WndEventArgs
wParam As Long
lParam As Long
hWnd As Dword
hInst As Dword
End Type
Sub GridSetup(Byref pGrid As IMSFlexGrid)
pGrid.FontName = "Times New Roman"
pGrid.FontSize = 10
pGrid.Cols = 4
pGrid.Rows = 20
pGrid.ColWidth(0) = 200
pGrid.ColWidth(1) = 1400
pGrid.ColWidth(2) = 1400
pGrid.ColWidth(3) = 1400
pGrid.Col = 1
pGrid.Row = 0
pGrid.Text = "Column 1"
pGrid.Col = 2
pGrid.Text = "Column 2"
pGrid.Col = 3
pGrid.Text = "Column 3"
End Sub
Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
Local lpCreateStruct As CREATESTRUCT Ptr
Local pEvents As DMSFlexGridEventsImpl
Local pGrid As IMSFlexGrid
Local hCtl As Dword
lpCreateStruct=Wea.lParam : Wea.hInst=@lpCreateStruct.hInstance
Call OC_WinInit()
hCtl=CreateWindowEx _
( _
0, _
$OC_ClassNAME, _
"MSFlexGridLib.MSFlexGrid;RTLKEY:72E67120-5959-11cf-91F6-C2863C385E30", _
%WS_CHILD OR %WS_VISIBLE, _
10, _
10, _
280, _
250, _
Wea.hWnd, _
%ID_CONTAINER, _
Wea.hInst, _
Byval %NULL _
)
pGrid=OC_GetDispatch(hCtl)
pGrid.AddRef()
SetWindowLong(Wea.hWnd,0,Objptr(pGrid))
If IsObject(pGrid) Then
pEvents = Class "CDMSFlexGridEvents"
If IsObject(pEvents) Then
SetWindowLong(Wea.hWnd,4,Objptr(pEvents))
Events From pGrid Call pEvents
Call GridSetup(pGrid)
Else
pGrid=Nothing
End If
End If
fnWndProc_OnCreate=0
End Function
Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
Local pEvents As DMSFlexGridEventsImpl
Local pGrid As IMSFlexGrid
Local dwObj As Dword
dwObj=GetWindowLong(Wea.hWnd,4)
CObj(pEvents,dwObj)
If dwObj Then
Events End pEvents
Set pEvents=Nothing
dwObj=0
End If
dwObj=GetWindowLong(Wea.hWnd,0)
If dwObj Then
CObj(pGrid,dwObj)
Set pGrid=Nothing
End If
Call PostQuitMessage(0)
fnWndProc_OnDestroy=0
End Function
Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
Local Wea As WndEventArgs
Select Case As Long wMsg
Case %WM_CREATE
Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
fnWndProc=fnWndProc_OnCreate(Wea)
Exit Function
Case %WM_DESTROY
Call PostQuitMessage(0)
fnWndProc=fnWndProc_OnDestroy(Wea)
Exit Function
End Select
fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function
Function WinMain(ByVal hInstance As Long, ByVal hPrevIns As Long, ByVal lpCmdLn As WStringz Ptr, ByVal iShow As Long) As Long
Local szAppName As WStringz*16
Local wc As WNDCLASSEX
Local Msg As tagMsg
Local hWnd As Dword
szAppName="OCX Test"
wc.lpszClassName=VarPtr(szAppName) : wc.lpfnWndProc=CodePtr(fnWndProc)
wc.cbSize=SizeOf(wc) : wc.cbWndExtra=8
wc.hInstance=hInstance : wc.hIcon=LoadIcon(%NULL,ByVal %IDI_APPLICATION)
wc.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW) : wc.hbrBackground=%COLOR_BTNFACE+1
Call RegisterClassEx(wc)
hWnd=CreateWindow(szAppName,"Jose's MSFlexGrid",%WS_OVERLAPPEDWINDOW Xor %WS_MAXIMIZEBOX,200,100,310,310,0,0,hInstance,ByVal 0)
Call ShowWindow(hWnd,iShow)
While GetMessage(Msg,%NULL,0,0)
TranslateMessage Msg
DispatchMessage Msg
Wend
Function=msg.wParam
End Function
Jose's TypeLib Browser produces these two include files. Jose seperates the 'incoming' and 'outgoing' interfaces...
This is so massive I can't get it all in one post. So I'm breaking MSFlexGridLib.inc into four posts...
'MSFlexGridLib.inc
' ########################################################################################
' Library name: MSFlexGridLib
' Version: 1.0, Locale ID = 0
' Description: Microsoft FlexGrid Control 6.0 (SP6)
' Path: C:\Windows\SysWow64\MSFLXGRD.OCX
' Library GUID: {5E9E78A0-531B-11CF-91F6-C2863C385E30}
' Help file: C:\Windows\HELP\MSHFlx98.chm
' License key: 72E67120-5959-11cf-91F6-C2863C385E30
' Code generated by the TypeLib Browser 5.0.1 (c) 2011 by José Roca
' Date: 05 Sep 2014 Time: 09:16:28
' Options used to generate the code:
' - Use METHOD and PROPERTY GET/SET statements
' - Use SET_ instead of PUT_ as prefix
' - Use parameter names in interface declarations
' - Add prefix in parameter names
' - Use interface names with external objects
' - Use enumeration names as prefix in constants
' - Include dispatch only interfaces
' - Retrieve license key
' ########################################################################################
' ========================================================================================
' CoClass name: DataObject
' ========================================================================================
' CLSID (Class identifier): {2334D2B2-713E-11CF-8AE5-00AA00C00905}
' Default interface: IVBDataObject
' Default interface IID: {2334D2B1-713E-11CF-8AE5-00AA00C00905}
' Implemented interfaces:
' IVBDataObject (default interface)
' ========================================================================================
' ========================================================================================
' CoClass name: DataObjectFiles
' ========================================================================================
' CLSID (Class identifier): {2334D2B4-713E-11CF-8AE5-00AA00C00905}
' Default interface: IVBDataObjectFiles
' Default interface IID: {2334D2B3-713E-11CF-8AE5-00AA00C00905}
' Implemented interfaces:
' IVBDataObjectFiles (default interface)
' ========================================================================================
' ========================================================================================
' CoClass name: MSFlexGrid
' ========================================================================================
' CLSID (Class identifier): {6262D3A0-531B-11CF-91F6-C2863C385E30}
' Help string: Microsoft FlexGrid Control 6.0 (SP6)
' Attributes: 38 [&H00000026] [Cancreate] [Licensed] [Control]
' ProgID (Program identifier): MSFlexGridLib.MSFlexGrid.1
' Version independent ProgID: MSFlexGridLib.MSFlexGrid
' Default interface: IMSFlexGrid
' Default interface IID: {5F4DF280-531B-11CF-91F6-C2863C385E30}
' Default events interface: DMSFlexGridEvents
' Default events interface IID: {609602E0-531B-11CF-91F6-C2863C385E30}
' Implemented interfaces:
' IMSFlexGrid (default interface)
' DMSFlexGridEvents (default events interface)
' ========================================================================================
' ========================================================================================
' ProgIDs (Program identifiers)
' ========================================================================================
' CLSID = {6262D3A0-531B-11CF-91F6-C2863C385E30}
$PROGID_MSFlexGrid1 = "MSFlexGridLib.MSFlexGrid.1"
' ========================================================================================
' Version independent ProgIDs
' ========================================================================================
' CLSID = {6262D3A0-531B-11CF-91F6-C2863C385E30}
$PROGID_MSFlexGrid = "MSFlexGridLib.MSFlexGrid"
' ========================================================================================
' ClsIDs (Class identifiers)
' ========================================================================================
$CLSID_DataObject = GUID$("{2334D2B2-713E-11CF-8AE5-00AA00C00905}")
$CLSID_DataObjectFiles = GUID$("{2334D2B4-713E-11CF-8AE5-00AA00C00905}")
$CLSID_MSFlexGrid = GUID$("{6262D3A0-531B-11CF-91F6-C2863C385E30}")
' ========================================================================================
' IIDs (Interface identifiers)
' ========================================================================================
$IID_DMSFlexGridEvents = GUID$("{609602E0-531B-11CF-91F6-C2863C385E30}")
$IID_IMSFlexGrid = GUID$("{5F4DF280-531B-11CF-91F6-C2863C385E30}")
$IID_IRowCursor = GUID$("{9F6AA700-D188-11CD-AD48-00AA003C9CB6}")
$IID_IVBDataObject = GUID$("{2334D2B1-713E-11CF-8AE5-00AA00C00905}")
$IID_IVBDataObjectFiles = GUID$("{2334D2B3-713E-11CF-8AE5-00AA00C00905}")
' ========================================================================================
' OLEDragConstants enum
' IID: {D8898460-742F-11CF-8AEA-00AA00C00905}
' Constants for the OLEDragMode property (but not the DragMode or OLEDropMode properties).
' ========================================================================================
ENUM OLEDragConstants
flexOLEDragManual = 0 ' &H00000000
flexOLEDragAutomatic = 1 ' &H00000001
END ENUM
' ========================================================================================
' OLEDropConstants enum
' IID: {D8898461-742F-11CF-8AEA-00AA00C00905}
' Constants for the OLEDropMode property (but not the DragMode or OLEDragMode properties).
' ========================================================================================
ENUM OLEDropConstants
flexOLEDropNone = 0 ' &H00000000
flexOLEDropManual = 1 ' &H00000001
END ENUM
' ========================================================================================
' DragOverConstants enum
' IID: {D8898464-742F-11CF-8AEA-00AA00C00905}
' State transition constants for the DragOver and OLEDragOver events.
' ========================================================================================
ENUM DragOverConstants
flexEnter = 0 ' &H00000000
flexLeave = 1 ' &H00000001
flexOver = 2 ' &H00000002
END ENUM
' ========================================================================================
' ClipBoardConstants enum
' IID: {D8898462-742F-11CF-8AEA-00AA00C00905}
' Clipboard format constants.
' ========================================================================================
ENUM ClipBoardConstants
flexCFText = 1 ' &H00000001
flexCFBitmap = 2 ' &H00000002
flexCFMetafile = 3 ' &H00000003
flexCFDIB = 8 ' &H00000008
flexCFPalette = 9 ' &H00000009
flexCFEMetafile = 14 ' &H0000000E
flexCFFiles = 15 ' &H0000000F
flexCFRTF = -16639 ' &HFFFFBF01
END ENUM
' ========================================================================================
' OLEDropEffectConstants enum
' IID: {D8898463-742F-11CF-8AEA-00AA00C00905}
' Drop effect constants for OLE drag and drop events.
' ========================================================================================
ENUM OLEDropEffectConstants
flexOLEDropEffectNone = 0 ' &H00000000
flexOLEDropEffectCopy = 1 ' &H00000001
flexOLEDropEffectMove = 2 ' &H00000002
flexOLEDropEffectScroll = -2147483648 ' &H80000000
END ENUM
' ========================================================================================
' ErrorConstants enum
' Error constants
' ========================================================================================
ENUM ErrorConstants
flexerrIllegaFunctionCall = 5 ' &H00000005
flexerrObjIllegalUse = 425 ' &H000001A9
flexerrClipInvalidFormat = 461 ' &H000001CD
flexerrDataObjectLocked = 672 ' &H000002A0
flexerrExpectedAnArgument = 673 ' &H000002A1
flexerrRecursiveOLEDrag = 674 ' &H000002A2
flexerrUserFormatNotBinArray = 675 ' &H000002A3
flexerrDataNotSetForFormat = 676 ' &H000002A4
flexerrUnknownError = 600 ' &H00000258
flexerrSubscript = 381 ' &H0000017D
flexerrBadValue = 380 ' &H0000017C
flexerrGetNotSupported = 394 ' &H0000018A
flexerrSetNotPermitted = 387 ' &H00000183
flexerrOutOfMemory = 7 ' &H00000007
flexerrVB30000 = 30000 ' &H00007530
flexerrVB30001 = 30001 ' &H00007531
flexerrVB30002 = 30002 ' &H00007532
flexerrVB30004 = 30004 ' &H00007534
flexerrVB30005 = 30005 ' &H00007535
flexerrVB30006 = 30006 ' &H00007536
flexerrVB30008 = 30008 ' &H00007538
flexerrVB30009 = 30009 ' &H00007539
flexerrVB30010 = 30010 ' &H0000753A
flexerrVB30011 = 30011 ' &H0000753B
flexerrVB30013 = 30013 ' &H0000753D
flexerrVB30014 = 30014 ' &H0000753E
flexerrVB30015 = 30015 ' &H0000753F
flexerrVB30016 = 30016 ' &H00007540
flexerrVB30017 = 30017 ' &H00007541
END ENUM
' ========================================================================================
' AppearanceSettings enum
' Appearance Constants
' ========================================================================================
ENUM AppearanceSettings
flexFlat = 0 ' &H00000000
flex3D = 1 ' &H00000001
END ENUM
' ========================================================================================
' BorderStyleSettings enum
' BorderStyle Constants
' ========================================================================================
ENUM BorderStyleSettings
flexBorderNone = 0 ' &H00000000
flexBorderSingle = 1 ' &H00000001
END ENUM
' ========================================================================================
' FocusRectSettings enum
' FocusRect Constants
' ========================================================================================
ENUM FocusRectSettings
flexFocusNone = 0 ' &H00000000
flexFocusLight = 1 ' &H00000001
flexFocusHeavy = 2 ' &H00000002
END ENUM
' ========================================================================================
' HighLightSettings enum
' Highlight Constants
' ========================================================================================
ENUM HighLightSettings
flexHighlightNever = 0 ' &H00000000
flexHighlightAlways = 1 ' &H00000001
flexHighlightWithFocus = 2 ' &H00000002
END ENUM
' ========================================================================================
' ScrollBarsSettings enum
' ScrollBars Constants
' ========================================================================================
ENUM ScrollBarsSettings
flexScrollBarNone = 0 ' &H00000000
flexScrollBarHorizontal = 1 ' &H00000001
flexScrollBarVertical = 2 ' &H00000002
flexScrollBarBoth = 3 ' &H00000003
END ENUM
' ========================================================================================
' TextStyleSettings enum
' TextStyle Constants
' ========================================================================================
ENUM TextStyleSettings
flexTextFlat = 0 ' &H00000000
flexTextRaised = 1 ' &H00000001
flexTextInset = 2 ' &H00000002
flexTextRaisedLight = 3 ' &H00000003
flexTextInsetLight = 4 ' &H00000004
END ENUM
' ========================================================================================
' FillStyleSettings enum
' FillStyle Constants
' ========================================================================================
ENUM FillStyleSettings
flexFillSingle = 0 ' &H00000000
flexFillRepeat = 1 ' &H00000001
END ENUM
' ========================================================================================
' GridLineSettings enum
' GridLines Constants
' ========================================================================================
ENUM GridLineSettings
flexGridNone = 0 ' &H00000000
flexGridFlat = 1 ' &H00000001
flexGridInset = 2 ' &H00000002
flexGridRaised = 3 ' &H00000003
END ENUM
' ========================================================================================
' SelectionModeSettings enum
' SelectionMode Constants
' ========================================================================================
ENUM SelectionModeSettings
flexSelectionFree = 0 ' &H00000000
flexSelectionByRow = 1 ' &H00000001
flexSelectionByColumn = 2 ' &H00000002
END ENUM
' ========================================================================================
' MergeCellsSettings enum
' MergeCells Constants
' ========================================================================================
ENUM MergeCellsSettings
flexMergeNever = 0 ' &H00000000
flexMergeFree = 1 ' &H00000001
flexMergeRestrictRows = 2 ' &H00000002
flexMergeRestrictColumns = 3 ' &H00000003
flexMergeRestrictAll = 4 ' &H00000004
END ENUM
' ========================================================================================
' PictureTypeSettings enum
' PictureType Constants
' ========================================================================================
ENUM PictureTypeSettings
flexPictureColor = 0 ' &H00000000
flexPictureMonochrome = 1 ' &H00000001
END ENUM
' ========================================================================================
' AllowUserResizeSettings enum
' AllowUserResizing Constants
' ========================================================================================
ENUM AllowUserResizeSettings
flexResizeNone = 0 ' &H00000000
flexResizeColumns = 1 ' &H00000001
flexResizeRows = 2 ' &H00000002
flexResizeBoth = 3 ' &H00000003
END ENUM
' ========================================================================================
' MousePointerSettings enum
' MousePointer Constants
' ========================================================================================
ENUM MousePointerSettings
flexDefault = 0 ' &H00000000
flexArrow = 1 ' &H00000001
flexCross = 2 ' &H00000002
flexIBeam = 3 ' &H00000003
flexIcon = 4 ' &H00000004
flexSize = 5 ' &H00000005
flexSizeNESW = 6 ' &H00000006
flexSizeNS = 7 ' &H00000007
flexSizeNWSE = 8 ' &H00000008
flexSizeEW = 9 ' &H00000009
flexUpArrow = 10 ' &H0000000A
flexHourglass = 11 ' &H0000000B
flexNoDrop = 12 ' &H0000000C
flexArrowHourGlass = 13 ' &H0000000D
flexArrowQuestion = 14 ' &H0000000E
flexSizeAll = 15 ' &H0000000F
flexCustom = 99 ' &H00000063
END ENUM
' ========================================================================================
' SortSettings enum
' Sort Constants
' ========================================================================================
ENUM SortSettings
flexSortNone = 0 ' &H00000000
flexSortGenericAscending = 1 ' &H00000001
flexSortGenericDescending = 2 ' &H00000002
flexSortNumericAscending = 3 ' &H00000003
flexSortNumericDescending = 4 ' &H00000004
flexSortStringNoCaseAscending = 5 ' &H00000005
flexSortStringNoCaseDescending = 6 ' &H00000006
flexSortStringAscending = 7 ' &H00000007
flexSortStringDescending = 8 ' &H00000008
END ENUM
' ========================================================================================
' AlignmentSettings enum
' Alignment Constants
' ========================================================================================
ENUM AlignmentSettings
flexAlignLeftTop = 0 ' &H00000000
flexAlignLeftCenter = 1 ' &H00000001
flexAlignLeftBottom = 2 ' &H00000002
flexAlignCenterTop = 3 ' &H00000003
flexAlignCenterCenter = 4 ' &H00000004
flexAlignCenterBottom = 5 ' &H00000005
flexAlignRightTop = 6 ' &H00000006
flexAlignRightCenter = 7 ' &H00000007
flexAlignRightBottom = 8 ' &H00000008
flexAlignGeneral = 9 ' &H00000009
END ENUM
' ########################################################################################
' Interface name = IVBDataObject
' IID = {2334D2B1-713E-11CF-8AE5-00AA00C00905}
' Attributes = 4304 [&H000010D0] [Hidden] [Dual] [Nonextensible] [Dispatchable]
' Inherited interface = IDispatch
' ########################################################################################
#IF NOT %DEF(%IVBDataObject_INTERFACE_DEFINED)
%IVBDataObject_INTERFACE_DEFINED = 1
INTERFACE IVBDataObject $IID_IVBDataObject
INHERIT IDispatch
' =====================================================================================
METHOD Clear <1> ( _ ' VTable offset = 28
) ' void
' =====================================================================================
METHOD GetData <2> ( _ ' VTable offset = 32
BYVAL prm_sFormat AS INTEGER _ ' [in] sFormat VT_I2 <Integer>
) AS VARIANT ' [retval][out] *pvData VT_VARIANT <Variant>
' =====================================================================================
METHOD GetFormat <3> ( _ ' VTable offset = 36
BYVAL prm_sFormat AS INTEGER _ ' [in] sFormat VT_I2 <Integer>
) AS INTEGER ' [retval][out] *pbFormatSupported VT_BOOL <Integer>
' =====================================================================================
METHOD SetData <4> ( _ ' VTable offset = 40
OPTIONAL BYVAL prm_vValue AS VARIANT _ ' [opt][in] vValue VT_VARIANT <Variant>
, OPTIONAL BYVAL prm_vFormat AS VARIANT _ ' [opt][in] vFormat VT_VARIANT <Variant>
) ' void
' =====================================================================================
PROPERTY GET Files <5> ( _ ' VTable offset = 44
) AS IVBDataObjectFiles ' [retval][out] **pFiles IVBDataObjectFiles <dispinterface>
' =====================================================================================
END INTERFACE
#ENDIF ' /* __IVBDataObject_INTERFACE_DEFINED__ */
' ########################################################################################
' Interface name = IVBDataObjectFiles
' IID = {2334D2B3-713E-11CF-8AE5-00AA00C00905}
' Attributes = 4304 [&H000010D0] [Hidden] [Dual] [Nonextensible] [Dispatchable]
' Inherited interface = IDispatch
' ########################################################################################
#IF NOT %DEF(%IVBDataObjectFiles_INTERFACE_DEFINED)
%IVBDataObjectFiles_INTERFACE_DEFINED = 1
INTERFACE IVBDataObjectFiles $IID_IVBDataObjectFiles
INHERIT IDispatch
' =====================================================================================
PROPERTY GET Item <0> ( _ ' VTable offset = 28
BYVAL prm_lIndex AS LONG _ ' [in] lIndex VT_I4 <Long>
) AS WSTRING ' [retval][out] *bstrItem VT_BSTR
' =====================================================================================
PROPERTY GET Count <1> ( _ ' VTable offset = 32
) AS LONG ' [retval][out] *plCount VT_I4 <Long>
' =====================================================================================
METHOD Add <2> ( _ ' VTable offset = 36
BYVAL prm_bstrFilename AS WSTRING _ ' [in] bstrFilename VT_BSTR
, OPTIONAL BYVAL prm_vIndex AS VARIANT _ ' [opt][in] vIndex VT_VARIANT <Variant>
) ' void
' =====================================================================================
METHOD Clear <3> ( _ ' VTable offset = 40
) ' void
' =====================================================================================
METHOD Remove <4> ( _ ' VTable offset = 44
BYVAL prm_vIndex AS VARIANT _ ' [in] vIndex VT_VARIANT <Variant>
) ' void
' =====================================================================================
METHOD NewEnum_ <-4> ( _ ' VTable offset = 48
) AS IUnknown ' [retval][out] **ppUnk VT_UNKNOWN <IUnknown>
' =====================================================================================
END INTERFACE
#ENDIF ' /* __IVBDataObjectFiles_INTERFACE_DEFINED__ */
' ########################################################################################
' Interface name = IRowCursor
' IID = {9F6AA700-D188-11CD-AD48-00AA003C9CB6}
' Attributes = 4176 [&H00001050] [Hidden] [Dual] [Dispatchable]
' Inherited interface = IDispatch
' ########################################################################################
#IF NOT %DEF(%IRowCursor_INTERFACE_DEFINED)
%IRowCursor_INTERFACE_DEFINED = 1
INTERFACE IRowCursor $IID_IRowCursor
INHERIT IDispatch
END INTERFACE
#ENDIF ' /* __IRowCursor_INTERFACE_DEFINED__ */
MSFlexGridLib.inc continued .....
...MSFlexGridLib.inc continued - part 2 ...
' ########################################################################################
' Interface name = IMSFlexGrid
' IID = {5F4DF280-531B-11CF-91F6-C2863C385E30}
' Dispatch interface for Microsoft FlexGrid Control
' Attributes = 4304 [&H000010D0] [Hidden] [Dual] [Nonextensible] [Dispatchable]
' Inherited interface = IDispatch
' ########################################################################################
#IF NOT %DEF(%IMSFlexGrid_INTERFACE_DEFINED)
%IMSFlexGrid_INTERFACE_DEFINED = 1
INTERFACE IMSFlexGrid $IID_IMSFlexGrid
INHERIT IDispatch
' =====================================================================================
PROPERTY GET Rows <4> ( _ ' VTable offset = 28
) AS LONG ' [retval][out] *Rows VT_I4 <Long>
' =====================================================================================
PROPERTY SET Rows <4> ( _ ' VTable offset = 32
BYVAL prm_Rows AS LONG _ ' [in] Rows VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET Cols <5> ( _ ' VTable offset = 36
) AS LONG ' [retval][out] *Cols VT_I4 <Long>
' =====================================================================================
PROPERTY SET Cols <5> ( _ ' VTable offset = 40
BYVAL prm_Cols AS LONG _ ' [in] Cols VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET FixedRows <6> ( _ ' VTable offset = 44
) AS LONG ' [retval][out] *FixedRows VT_I4 <Long>
' =====================================================================================
PROPERTY SET FixedRows <6> ( _ ' VTable offset = 48
BYVAL prm_FixedRows AS LONG _ ' [in] FixedRows VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET FixedCols <7> ( _ ' VTable offset = 52
) AS LONG ' [retval][out] *FixedCols VT_I4 <Long>
' =====================================================================================
PROPERTY SET FixedCols <7> ( _ ' VTable offset = 56
BYVAL prm_FixedCols AS LONG _ ' [in] FixedCols VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET Version <1> ( _ ' VTable offset = 60
) AS INTEGER ' [retval][out] *Version VT_I2 <Integer>
' =====================================================================================
PROPERTY GET FormatString <2> ( _ ' VTable offset = 64
) AS WSTRING ' [retval][out] *FormatString VT_BSTR
' =====================================================================================
PROPERTY SET FormatString <2> ( _ ' VTable offset = 68
BYVAL prm_FormatString AS WSTRING _ ' [in] FormatString VT_BSTR
) ' void
' =====================================================================================
PROPERTY GET TopRow <8> ( _ ' VTable offset = 72
) AS LONG ' [retval][out] *TopRow VT_I4 <Long>
' =====================================================================================
PROPERTY SET TopRow <8> ( _ ' VTable offset = 76
BYVAL prm_TopRow AS LONG _ ' [in] TopRow VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET LeftCol <9> ( _ ' VTable offset = 80
) AS LONG ' [retval][out] *LeftCol VT_I4 <Long>
' =====================================================================================
PROPERTY SET LeftCol <9> ( _ ' VTable offset = 84
BYVAL prm_LeftCol AS LONG _ ' [in] LeftCol VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET Row <10> ( _ ' VTable offset = 88
) AS LONG ' [retval][out] *Row VT_I4 <Long>
' =====================================================================================
PROPERTY SET Row <10> ( _ ' VTable offset = 92
BYVAL prm_Row AS LONG _ ' [in] Row VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET Col <11> ( _ ' VTable offset = 96
) AS LONG ' [retval][out] *Col VT_I4 <Long>
' =====================================================================================
PROPERTY SET Col <11> ( _ ' VTable offset = 100
BYVAL prm_Col AS LONG _ ' [in] Col VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET RowSel <12> ( _ ' VTable offset = 104
) AS LONG ' [retval][out] *RowSel VT_I4 <Long>
' =====================================================================================
PROPERTY SET RowSel <12> ( _ ' VTable offset = 108
BYVAL prm_RowSel AS LONG _ ' [in] RowSel VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET ColSel <13> ( _ ' VTable offset = 112
) AS LONG ' [retval][out] *ColSel VT_I4 <Long>
' =====================================================================================
PROPERTY SET ColSel <13> ( _ ' VTable offset = 116
BYVAL prm_ColSel AS LONG _ ' [in] ColSel VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET Text <0> ( _ ' VTable offset = 120
) AS WSTRING ' [retval][out] *Text VT_BSTR
' =====================================================================================
PROPERTY SET Text <0> ( _ ' VTable offset = 124
BYVAL prm_Text AS WSTRING _ ' [in] Text VT_BSTR
) ' void
' =====================================================================================
PROPERTY GET BackColor <-501> ( _ ' VTable offset = 128
) AS DWORD ' [retval][out] *BackColor OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET BackColor <-501> ( _ ' VTable offset = 132
BYVAL prm_BackColor AS DWORD _ ' [in] BackColor OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET ForeColor <-513> ( _ ' VTable offset = 136
) AS DWORD ' [retval][out] *ForeColor OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET ForeColor <-513> ( _ ' VTable offset = 140
BYVAL prm_ForeColor AS DWORD _ ' [in] ForeColor OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET BackColorFixed <14> ( _ ' VTable offset = 144
) AS DWORD ' [retval][out] *BackColorFixed OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET BackColorFixed <14> ( _ ' VTable offset = 148
BYVAL prm_BackColorFixed AS DWORD _ ' [in] BackColorFixed OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET ForeColorFixed <15> ( _ ' VTable offset = 152
) AS DWORD ' [retval][out] *ForeColorFixed OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET ForeColorFixed <15> ( _ ' VTable offset = 156
BYVAL prm_ForeColorFixed AS DWORD _ ' [in] ForeColorFixed OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET BackColorSel <16> ( _ ' VTable offset = 160
) AS DWORD ' [retval][out] *BackColorSel OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET BackColorSel <16> ( _ ' VTable offset = 164
BYVAL prm_BackColorSel AS DWORD _ ' [in] BackColorSel OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET ForeColorSel <17> ( _ ' VTable offset = 168
) AS DWORD ' [retval][out] *ForeColorSel OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET ForeColorSel <17> ( _ ' VTable offset = 172
BYVAL prm_ForeColorSel AS DWORD _ ' [in] ForeColorSel OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET BackColorBkg <18> ( _ ' VTable offset = 176
) AS DWORD ' [retval][out] *BackColorBkg OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET BackColorBkg <18> ( _ ' VTable offset = 180
BYVAL prm_BackColorBkg AS DWORD _ ' [in] BackColorBkg OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET WordWrap <19> ( _ ' VTable offset = 184
) AS INTEGER ' [retval][out] *WordWrap VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET WordWrap <19> ( _ ' VTable offset = 188
BYVAL prm_WordWrap AS INTEGER _ ' [in] WordWrap VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET Font <-512> ( _ ' VTable offset = 192
) AS IFontDisp ' [retval][out] **Font IFontDisp <alias> Font
' =====================================================================================
PROPERTY SET putref_Font <-512> ( _ ' VTable offset = 196
BYVAL prm_Font AS IFontDisp _ ' [in] *Font IFontDisp <alias> Font
) ' void
' =====================================================================================
PROPERTY GET FontWidth <84> ( _ ' VTable offset = 200
) AS SINGLE ' [retval][out] *FontWidth VT_R4 <Single>
' =====================================================================================
PROPERTY SET FontWidth <84> ( _ ' VTable offset = 204
BYVAL prm_FontWidth AS SINGLE _ ' [in] FontWidth VT_R4 <Single>
) ' void
' =====================================================================================
PROPERTY GET CellFontName <77> ( _ ' VTable offset = 208
) AS WSTRING ' [retval][out] *CellFontName VT_BSTR
' =====================================================================================
PROPERTY SET CellFontName <77> ( _ ' VTable offset = 212
BYVAL prm_CellFontName AS WSTRING _ ' [in] CellFontName VT_BSTR
) ' void
' =====================================================================================
PROPERTY GET CellFontSize <78> ( _ ' VTable offset = 216
) AS SINGLE ' [retval][out] *CellFontSize VT_R4 <Single>
' =====================================================================================
PROPERTY SET CellFontSize <78> ( _ ' VTable offset = 220
BYVAL prm_CellFontSize AS SINGLE _ ' [in] CellFontSize VT_R4 <Single>
) ' void
' =====================================================================================
PROPERTY GET CellFontBold <79> ( _ ' VTable offset = 224
) AS INTEGER ' [retval][out] *CellFontBold VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET CellFontBold <79> ( _ ' VTable offset = 228
BYVAL prm_CellFontBold AS INTEGER _ ' [in] CellFontBold VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET CellFontItalic <80> ( _ ' VTable offset = 232
) AS INTEGER ' [retval][out] *CellFontItalic VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET CellFontItalic <80> ( _ ' VTable offset = 236
BYVAL prm_CellFontItalic AS INTEGER _ ' [in] CellFontItalic VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET CellFontUnderline <81> ( _ ' VTable offset = 240
) AS INTEGER ' [retval][out] *CellFontUnderline VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET CellFontUnderline <81> ( _ ' VTable offset = 244
BYVAL prm_CellFontUnderline AS INTEGER _ ' [in] CellFontUnderline VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET CellFontStrikeThrough <82> ( _ ' VTable offset = 248
) AS INTEGER ' [retval][out] *CellFontStrikeThrough VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET CellFontStrikeThrough <82> ( _ ' VTable offset = 252
BYVAL prm_CellFontStrikeThrough AS INTEGER _ ' [in] CellFontStrikeThrough VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET CellFontWidth <83> ( _ ' VTable offset = 256
) AS SINGLE ' [retval][out] *CellFontWidth VT_R4 <Single>
' =====================================================================================
PROPERTY SET CellFontWidth <83> ( _ ' VTable offset = 260
BYVAL prm_CellFontWidth AS SINGLE _ ' [in] CellFontWidth VT_R4 <Single>
) ' void
' =====================================================================================
PROPERTY GET TextStyle <20> ( _ ' VTable offset = 264
) AS LONG ' [retval][out] *TextStyle TextStyleSettings <enum>
' =====================================================================================
PROPERTY SET TextStyle <20> ( _ ' VTable offset = 268
BYVAL prm_TextStyle AS LONG _ ' [in] TextStyle TextStyleSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET TextStyleFixed <21> ( _ ' VTable offset = 272
) AS LONG ' [retval][out] *TextStyleFixed TextStyleSettings <enum>
' =====================================================================================
PROPERTY SET TextStyleFixed <21> ( _ ' VTable offset = 276
BYVAL prm_TextStyleFixed AS LONG _ ' [in] TextStyleFixed TextStyleSettings <enum>
) ' void
' =====================================================================================
...continued MSFlexGridLib.inc - part 3 ...
PROPERTY GET ScrollTrack <22> ( _ ' VTable offset = 280
) AS INTEGER ' [retval][out] *ScrollTrack VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET ScrollTrack <22> ( _ ' VTable offset = 284
BYVAL prm_ScrollTrack AS INTEGER _ ' [in] ScrollTrack VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET FocusRect <23> ( _ ' VTable offset = 288
) AS LONG ' [retval][out] *FocusRect FocusRectSettings <enum>
' =====================================================================================
PROPERTY SET FocusRect <23> ( _ ' VTable offset = 292
BYVAL prm_FocusRect AS LONG _ ' [in] FocusRect FocusRectSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET HighLight <24> ( _ ' VTable offset = 296
) AS LONG ' [retval][out] *HighLight HighLightSettings <enum>
' =====================================================================================
PROPERTY SET HighLight <24> ( _ ' VTable offset = 300
BYVAL prm_HighLight AS LONG _ ' [in] HighLight HighLightSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET Redraw <25> ( _ ' VTable offset = 304
) AS INTEGER ' [retval][out] *Redraw VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET Redraw <25> ( _ ' VTable offset = 308
BYVAL prm_Redraw AS INTEGER _ ' [in] Redraw VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET ScrollBars <26> ( _ ' VTable offset = 312
) AS LONG ' [retval][out] *ScrollBars ScrollBarsSettings <enum>
' =====================================================================================
PROPERTY SET ScrollBars <26> ( _ ' VTable offset = 316
BYVAL prm_ScrollBars AS LONG _ ' [in] ScrollBars ScrollBarsSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET MouseRow <27> ( _ ' VTable offset = 320
) AS LONG ' [retval][out] *MouseRow VT_I4 <Long>
' =====================================================================================
PROPERTY GET MouseCol <28> ( _ ' VTable offset = 324
) AS LONG ' [retval][out] *MouseCol VT_I4 <Long>
' =====================================================================================
PROPERTY GET CellLeft <29> ( _ ' VTable offset = 328
) AS LONG ' [retval][out] *CellLeft VT_I4 <Long>
' =====================================================================================
PROPERTY GET CellTop <30> ( _ ' VTable offset = 332
) AS LONG ' [retval][out] *CellTop VT_I4 <Long>
' =====================================================================================
PROPERTY GET CellWidth <31> ( _ ' VTable offset = 336
) AS LONG ' [retval][out] *CellWidth VT_I4 <Long>
' =====================================================================================
PROPERTY GET CellHeight <32> ( _ ' VTable offset = 340
) AS LONG ' [retval][out] *CellHeight VT_I4 <Long>
' =====================================================================================
PROPERTY GET RowHeightMin <33> ( _ ' VTable offset = 344
) AS LONG ' [retval][out] *RowHeightMin VT_I4 <Long>
' =====================================================================================
PROPERTY SET RowHeightMin <33> ( _ ' VTable offset = 348
BYVAL prm_RowHeightMin AS LONG _ ' [in] RowHeightMin VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET FillStyle <-511> ( _ ' VTable offset = 352
) AS LONG ' [retval][out] *FillStyle FillStyleSettings <enum>
' =====================================================================================
PROPERTY SET FillStyle <-511> ( _ ' VTable offset = 356
BYVAL prm_FillStyle AS LONG _ ' [in] FillStyle FillStyleSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET GridLines <34> ( _ ' VTable offset = 360
) AS LONG ' [retval][out] *GridLines GridLineSettings <enum>
' =====================================================================================
PROPERTY SET GridLines <34> ( _ ' VTable offset = 364
BYVAL prm_GridLines AS LONG _ ' [in] GridLines GridLineSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET GridLinesFixed <35> ( _ ' VTable offset = 368
) AS LONG ' [retval][out] *GridLinesFixed GridLineSettings <enum>
' =====================================================================================
PROPERTY SET GridLinesFixed <35> ( _ ' VTable offset = 372
BYVAL prm_GridLinesFixed AS LONG _ ' [in] GridLinesFixed GridLineSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET GridColor <36> ( _ ' VTable offset = 376
) AS DWORD ' [retval][out] *GridColor OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET GridColor <36> ( _ ' VTable offset = 380
BYVAL prm_GridColor AS DWORD _ ' [in] GridColor OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET GridColorFixed <37> ( _ ' VTable offset = 384
) AS DWORD ' [retval][out] *GridColorFixed OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET GridColorFixed <37> ( _ ' VTable offset = 388
BYVAL prm_GridColorFixed AS DWORD _ ' [in] GridColorFixed OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET CellBackColor <38> ( _ ' VTable offset = 392
) AS DWORD ' [retval][out] *CellBackColor OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET CellBackColor <38> ( _ ' VTable offset = 396
BYVAL prm_CellBackColor AS DWORD _ ' [in] CellBackColor OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET CellForeColor <39> ( _ ' VTable offset = 400
) AS DWORD ' [retval][out] *CellForeColor OLE_COLOR <alias> <VT_UI4>
' =====================================================================================
PROPERTY SET CellForeColor <39> ( _ ' VTable offset = 404
BYVAL prm_CellForeColor AS DWORD _ ' [in] CellForeColor OLE_COLOR <alias> <VT_UI4>
) ' void
' =====================================================================================
PROPERTY GET CellAlignment <40> ( _ ' VTable offset = 408
) AS INTEGER ' [retval][out] *CellAlignment VT_I2 <Integer>
' =====================================================================================
PROPERTY SET CellAlignment <40> ( _ ' VTable offset = 412
BYVAL prm_CellAlignment AS INTEGER _ ' [in] CellAlignment VT_I2 <Integer>
) ' void
' =====================================================================================
PROPERTY GET CellTextStyle <41> ( _ ' VTable offset = 416
) AS LONG ' [retval][out] *CellTextStyle TextStyleSettings <enum>
' =====================================================================================
PROPERTY SET CellTextStyle <41> ( _ ' VTable offset = 420
BYVAL prm_CellTextStyle AS LONG _ ' [in] CellTextStyle TextStyleSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET CellPictureAlignment <43> ( _ ' VTable offset = 424
) AS INTEGER ' [retval][out] *CellPictureAlignment VT_I2 <Integer>
' =====================================================================================
PROPERTY SET CellPictureAlignment <43> ( _ ' VTable offset = 428
BYVAL prm_CellPictureAlignment AS INTEGER _ ' [in] CellPictureAlignment VT_I2 <Integer>
) ' void
' =====================================================================================
PROPERTY GET Clip <45> ( _ ' VTable offset = 432
) AS WSTRING ' [retval][out] *Clip VT_BSTR
' =====================================================================================
PROPERTY SET Clip <45> ( _ ' VTable offset = 436
BYVAL prm_Clip AS WSTRING _ ' [in] Clip VT_BSTR
) ' void
' =====================================================================================
PROPERTY SET Sort <46> ( _ ' VTable offset = 440
BYVAL prm_prm1 AS INTEGER _ ' [in] VT_I2 <Integer>
) ' void
' =====================================================================================
PROPERTY GET SelectionMode <47> ( _ ' VTable offset = 444
) AS LONG ' [retval][out] *SelectionMode SelectionModeSettings <enum>
' =====================================================================================
PROPERTY SET SelectionMode <47> ( _ ' VTable offset = 448
BYVAL prm_SelectionMode AS LONG _ ' [in] SelectionMode SelectionModeSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET MergeCells <48> ( _ ' VTable offset = 452
) AS LONG ' [retval][out] *MergeCells MergeCellsSettings <enum>
' =====================================================================================
PROPERTY SET MergeCells <48> ( _ ' VTable offset = 456
BYVAL prm_MergeCells AS LONG _ ' [in] MergeCells MergeCellsSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET AllowBigSelection <51> ( _ ' VTable offset = 460
) AS INTEGER ' [retval][out] *AllowBigSelection VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET AllowBigSelection <51> ( _ ' VTable offset = 464
BYVAL prm_AllowBigSelection AS INTEGER _ ' [in] AllowBigSelection VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET AllowUserResizing <52> ( _ ' VTable offset = 468
) AS LONG ' [retval][out] *AllowUserResizing AllowUserResizeSettings <enum>
' =====================================================================================
PROPERTY SET AllowUserResizing <52> ( _ ' VTable offset = 472
BYVAL prm_AllowUserResizing AS LONG _ ' [in] AllowUserResizing AllowUserResizeSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET BorderStyle <-504> ( _ ' VTable offset = 476
) AS LONG ' [retval][out] *BorderStyle BorderStyleSettings <enum>
' =====================================================================================
PROPERTY SET BorderStyle <-504> ( _ ' VTable offset = 480
BYVAL prm_BorderStyle AS LONG _ ' [in] BorderStyle BorderStyleSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET hWnd <-515> ( _ ' VTable offset = 484
) AS LONG ' [retval][out] *hWnd VT_I4 <Long>
' =====================================================================================
PROPERTY GET Enabled <-514> ( _ ' VTable offset = 488
) AS INTEGER ' [retval][out] *Enabled VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET Enabled <-514> ( _ ' VTable offset = 492
BYVAL prm_Enabled AS INTEGER _ ' [in] Enabled VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET Appearance <-520> ( _ ' VTable offset = 496
) AS LONG ' [retval][out] *Appearance AppearanceSettings <enum>
' =====================================================================================
PROPERTY SET Appearance <-520> ( _ ' VTable offset = 500
BYVAL prm_Appearance AS LONG _ ' [in] Appearance AppearanceSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET MousePointer <53> ( _ ' VTable offset = 504
) AS LONG ' [retval][out] *MousePointer MousePointerSettings <enum>
' =====================================================================================
PROPERTY SET MousePointer <53> ( _ ' VTable offset = 508
BYVAL prm_MousePointer AS LONG _ ' [in] MousePointer MousePointerSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET MouseIcon <54> ( _ ' VTable offset = 512
) AS IPictureDisp ' [retval][out] **MouseIcon IPictureDisp <alias> Picture
' =====================================================================================
PROPERTY SET putref_MouseIcon <54> ( _ ' VTable offset = 516
BYVAL prm_MouseIcon AS IPictureDisp _ ' [in] *MouseIcon IPictureDisp <alias> Picture
) ' void
' =====================================================================================
PROPERTY GET PictureType <50> ( _ ' VTable offset = 520
) AS LONG ' [retval][out] *PictureType PictureTypeSettings <enum>
' =====================================================================================
PROPERTY SET PictureType <50> ( _ ' VTable offset = 524
BYVAL prm_PictureType AS LONG _ ' [in] PictureType PictureTypeSettings <enum>
) ' void
' =====================================================================================
PROPERTY GET Picture <49> ( _ ' VTable offset = 528
) AS IPictureDisp ' [retval][out] **Picture IPictureDisp <alias> Picture
' =====================================================================================
PROPERTY GET CellPicture <42> ( _ ' VTable offset = 532
) AS IPictureDisp ' [retval][out] **CellPicture IPictureDisp <alias> Picture
' =====================================================================================
PROPERTY SET putref_CellPicture <42> ( _ ' VTable offset = 536
BYVAL prm_CellPicture AS IPictureDisp _ ' [in] *CellPicture IPictureDisp <alias> Picture
) ' void
' =====================================================================================
METHOD AboutBox <-552> ( _ ' VTable offset = 540
) ' void
' =====================================================================================
PROPERTY GET TextArray <55> ( _ ' VTable offset = 544
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS WSTRING ' [retval][out] *TextArray VT_BSTR
' =====================================================================================
PROPERTY SET TextArray <55> ( _ ' VTable offset = 548
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_TextArray AS WSTRING _ ' [in] TextArray VT_BSTR
) ' void
' =====================================================================================
PROPERTY GET ColAlignment <56> ( _ ' VTable offset = 552
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS INTEGER ' [retval][out] *ColAlignment VT_I2 <Integer>
' =====================================================================================
PROPERTY SET ColAlignment <56> ( _ ' VTable offset = 556
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_ColAlignment AS INTEGER _ ' [in] ColAlignment VT_I2 <Integer>
) ' void
' =====================================================================================
PROPERTY GET ColWidth <57> ( _ ' VTable offset = 560
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS LONG ' [retval][out] *ColWidth VT_I4 <Long>
' =====================================================================================
PROPERTY SET ColWidth <57> ( _ ' VTable offset = 564
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_ColWidth AS LONG _ ' [in] ColWidth VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET RowHeight <58> ( _ ' VTable offset = 568
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS LONG ' [retval][out] *RowHeight VT_I4 <Long>
' =====================================================================================
PROPERTY SET RowHeight <58> ( _ ' VTable offset = 572
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_RowHeight AS LONG _ ' [in] RowHeight VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET MergeRow <59> ( _ ' VTable offset = 576
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS INTEGER ' [retval][out] *MergeRow VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET MergeRow <59> ( _ ' VTable offset = 580
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_MergeRow AS INTEGER _ ' [in] MergeRow VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET MergeCol <60> ( _ ' VTable offset = 584
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS INTEGER ' [retval][out] *MergeCol VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET MergeCol <60> ( _ ' VTable offset = 588
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_MergeCol AS INTEGER _ ' [in] MergeCol VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY SET RowPosition <61> ( _ ' VTable offset = 592
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_prm2 AS LONG _ ' [in] VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY SET ColPosition <62> ( _ ' VTable offset = 596
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_prm2 AS LONG _ ' [in] VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET RowData <63> ( _ ' VTable offset = 600
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS LONG ' [retval][out] *RowData VT_I4 <Long>
' =====================================================================================
PROPERTY SET RowData <63> ( _ ' VTable offset = 604
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_RowData AS LONG _ ' [in] RowData VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET ColData <64> ( _ ' VTable offset = 608
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS LONG ' [retval][out] *ColData VT_I4 <Long>
' =====================================================================================
PROPERTY SET ColData <64> ( _ ' VTable offset = 612
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_ColData AS LONG _ ' [in] ColData VT_I4 <Long>
) ' void
' =====================================================================================
PROPERTY GET TextMatrix <65> ( _ ' VTable offset = 616
BYVAL prm_Row AS LONG _ ' [in] Row VT_I4 <Long>
, BYVAL prm_Col AS LONG _ ' [in] Col VT_I4 <Long>
) AS WSTRING ' [retval][out] *TextMatrix VT_BSTR
' =====================================================================================
PROPERTY SET TextMatrix <65> ( _ ' VTable offset = 620
BYVAL prm_Row AS LONG _ ' [in] Row VT_I4 <Long>
, BYVAL prm_Col AS LONG _ ' [in] Col VT_I4 <Long>
, BYVAL prm_TextMatrix AS WSTRING _ ' [in] TextMatrix VT_BSTR
) ' void
' =====================================================================================
METHOD AddItem <66> ( _ ' VTable offset = 624
BYVAL prm_Item AS WSTRING _ ' [in] Item VT_BSTR
, OPTIONAL BYVAL prm_index AS VARIANT _ ' [opt][in] index VT_VARIANT <Variant>
) ' void
' =====================================================================================
METHOD RemoveItem <67> ( _ ' VTable offset = 628
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) ' void
' =====================================================================================
METHOD Clear <68> ( _ ' VTable offset = 632
) ' void
' =====================================================================================
METHOD Refresh <-550> ( _ ' VTable offset = 636
) ' void
' =====================================================================================
PROPERTY GET DataSource <76> ( _ ' VTable offset = 640
) AS IRowCursor ' [retval][out] **DataSource IRowCursor <dispinterface>
' =====================================================================================
PROPERTY SET DataSource <76> ( _ ' VTable offset = 644
BYVAL prm_DataSource AS IRowCursor _ ' [in] *DataSource IRowCursor <dispinterface>
) ' void
' =====================================================================================
PROPERTY GET RowIsVisible <85> ( _ ' VTable offset = 648
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS INTEGER ' [retval][out] *RowIsVisible VT_BOOL <Integer>
' =====================================================================================
PROPERTY GET ColIsVisible <86> ( _ ' VTable offset = 652
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS INTEGER ' [retval][out] *ColIsVisible VT_BOOL <Integer>
' =====================================================================================
PROPERTY GET RowPos <87> ( _ ' VTable offset = 656
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS LONG ' [retval][out] *RowPos VT_I4 <Long>
' =====================================================================================
PROPERTY GET ColPos <88> ( _ ' VTable offset = 660
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS LONG ' [retval][out] *ColPos VT_I4 <Long>
' =====================================================================================
PROPERTY GET GridLineWidth <89> ( _ ' VTable offset = 664
) AS INTEGER ' [retval][out] *GridLineWidth VT_I2 <Integer>
' =====================================================================================
PROPERTY SET GridLineWidth <89> ( _ ' VTable offset = 668
BYVAL prm_GridLineWidth AS INTEGER _ ' [in] GridLineWidth VT_I2 <Integer>
) ' void
' =====================================================================================
PROPERTY GET FixedAlignment <90> ( _ ' VTable offset = 672
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
) AS INTEGER ' [retval][out] *FixedAlignment VT_I2 <Integer>
' =====================================================================================
PROPERTY SET FixedAlignment <90> ( _ ' VTable offset = 676
BYVAL prm_index AS LONG _ ' [in] index VT_I4 <Long>
, BYVAL prm_FixedAlignment AS INTEGER _ ' [in] FixedAlignment VT_I2 <Integer>
) ' void
' =====================================================================================
PROPERTY GET FontName <91> ( _ ' VTable offset = 680
) AS WSTRING ' [retval][out] *FontName VT_BSTR
' =====================================================================================
PROPERTY SET FontName <91> ( _ ' VTable offset = 684
BYVAL prm_FontName AS WSTRING _ ' [in] FontName VT_BSTR
) ' void
' =====================================================================================
PROPERTY GET FontSize <92> ( _ ' VTable offset = 688
) AS SINGLE ' [retval][out] *FontSize VT_R4 <Single>
' =====================================================================================
PROPERTY SET FontSize <92> ( _ ' VTable offset = 692
BYVAL prm_FontSize AS SINGLE _ ' [in] FontSize VT_R4 <Single>
) ' void
' =====================================================================================
PROPERTY GET FontBold <93> ( _ ' VTable offset = 696
) AS INTEGER ' [retval][out] *FontBold VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET FontBold <93> ( _ ' VTable offset = 700
BYVAL prm_FontBold AS INTEGER _ ' [in] FontBold VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET FontItalic <94> ( _ ' VTable offset = 704
) AS INTEGER ' [retval][out] *FontItalic VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET FontItalic <94> ( _ ' VTable offset = 708
BYVAL prm_FontItalic AS INTEGER _ ' [in] FontItalic VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET FontStrikethru <95> ( _ ' VTable offset = 712
) AS INTEGER ' [retval][out] *FontStrikethru VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET FontStrikethru <95> ( _ ' VTable offset = 716
BYVAL prm_FontStrikethru AS INTEGER _ ' [in] FontStrikethru VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET FontUnderline <96> ( _ ' VTable offset = 720
) AS INTEGER ' [retval][out] *FontUnderline VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET FontUnderline <96> ( _ ' VTable offset = 724
BYVAL prm_FontUnderline AS INTEGER _ ' [in] FontUnderline VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET RightToLeft <-611> ( _ ' VTable offset = 728
) AS INTEGER ' [retval][out] *RightToLeft VT_BOOL <Integer>
' =====================================================================================
PROPERTY SET RightToLeft <-611> ( _ ' VTable offset = 732
BYVAL prm_RightToLeft AS INTEGER _ ' [in] RightToLeft VT_BOOL <Integer>
) ' void
' =====================================================================================
PROPERTY GET OLEDropMode <1551> ( _ ' VTable offset = 736
) AS LONG ' [retval][out] *psOLEDropMode OLEDropConstants <enum>
' =====================================================================================
PROPERTY SET OLEDropMode <1551> ( _ ' VTable offset = 740
BYVAL prm_psOLEDropMode AS LONG _ ' [in] psOLEDropMode OLEDropConstants <enum>
) ' void
' =====================================================================================
METHOD OLEDrag <1552> ( _ ' VTable offset = 744
) ' void
' =====================================================================================
END INTERFACE
#ENDIF ' /* __IMSFlexGrid_INTERFACE_DEFINED__ */
Dear God that was a struggle to get in! :) No more posting Jose's includes for me!!!
And here is the events code...
'MSFlexGridLibEvents.inc
' ########################################################################################
' Class CDMSFlexGridEvents
' Interface name = DMSFlexGridEvents
' IID = {609602E0-531B-11CF-91F6-C2863C385E30}
' Event interface for Microsoft FlexGrid Control
' Attributes = 4112 [&H1010] [Hidden] [Dispatchable]
' Code generated by the TypeLib Browser 5.0.1 (c) 2011 by José Roca
' Date: 05 Sep 2014 Time: 09:17:50
' ########################################################################################
CLASS CDMSFlexGridEvents GUID$("{16980577-F116-4460-85AD-71B208AD9996}") AS EVENT
INTERFACE DMSFlexGridEventsImpl GUID$("{609602E0-531B-11CF-91F6-C2863C385E30}") AS EVENT : INHERIT IDispatch
' =====================================================================================
METHOD Click <-600>
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD KeyDown <-602> ( _
BYREF prm_KeyCode AS INTEGER _ ' *KeyCode VT_I2 <Integer>
, BYVAL prm_Shift AS INTEGER _ ' Shift VT_I2 <Integer>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD DblClick <-601>
MsgBox("You Double Clicked In A Grid Cell!")
END METHOD
' =====================================================================================
' =====================================================================================
Method KeyPress <-603> (Byref KeyAscii As Integer)
MsgBox("You Pressed The Key " & Chr$(KeyAscii) & "!")
End Method
' =====================================================================================
' =====================================================================================
METHOD KeyUp <-604> ( _
BYREF prm_KeyCode AS INTEGER _ ' *KeyCode VT_I2 <Integer>
, BYVAL prm_Shift AS INTEGER _ ' Shift VT_I2 <Integer>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD MouseDown <-605> ( _
BYVAL prm_Button AS INTEGER _ ' Button VT_I2 <Integer>
, BYVAL prm_Shift AS INTEGER _ ' Shift VT_I2 <Integer>
, BYVAL prm_x AS LONG _ ' x OLE_XPOS_PIXELS <alias> <VT_I4>
, BYVAL prm_y AS LONG _ ' y OLE_YPOS_PIXELS <alias> <VT_I4>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD MouseMove <-606> ( _
BYVAL prm_Button AS INTEGER _ ' Button VT_I2 <Integer>
, BYVAL prm_Shift AS INTEGER _ ' Shift VT_I2 <Integer>
, BYVAL prm_x AS LONG _ ' x OLE_XPOS_PIXELS <alias> <VT_I4>
, BYVAL prm_y AS LONG _ ' y OLE_YPOS_PIXELS <alias> <VT_I4>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD MouseUp <-607> ( _
BYVAL prm_Button AS INTEGER _ ' Button VT_I2 <Integer>
, BYVAL prm_Shift AS INTEGER _ ' Shift VT_I2 <Integer>
, BYVAL prm_x AS LONG _ ' x OLE_XPOS_PIXELS <alias> <VT_I4>
, BYVAL prm_y AS LONG _ ' y OLE_YPOS_PIXELS <alias> <VT_I4>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD SelChange <69>
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD RowColChange <70>
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD EnterCell <71>
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD LeaveCell <72>
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD Scroll <73>
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD Compare <74> ( _
BYVAL prm_Row1 AS LONG _ ' Row1 VT_I4 <Long>
, BYVAL prm_Row2 AS LONG _ ' Row2 VT_I4 <Long>
, BYREF prm_Cmp AS INTEGER _ ' *Cmp VT_I2 <Integer>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD OLEStartDrag <1550> ( _
BYREF prm_Data AS IDispatch _ ' [in][out] **Data DataObject <coclass>
, BYREF prm_AllowedEffects AS LONG _ ' [in][out] *AllowedEffects VT_I4 <Long>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD OLEGiveFeedback <1551> ( _
BYREF prm_Effect AS LONG _ ' [in][out] *Effect VT_I4 <Long>
, BYREF prm_DefaultCursors AS INTEGER _ ' [in][out] *DefaultCursors VT_BOOL <Integer>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD OLESetData <1552> ( _
BYREF prm_Data AS IDispatch _ ' [in][out] **Data DataObject <coclass>
, BYREF prm_DataFormat AS INTEGER _ ' [in][out] *DataFormat VT_I2 <Integer>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD OLECompleteDrag <1553> ( _
BYREF prm_Effect AS LONG _ ' [in][out] *Effect VT_I4 <Long>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD OLEDragOver <1554> ( _
BYREF prm_Data AS IDispatch _ ' [in][out] **Data DataObject <coclass>
, BYREF prm_Effect AS LONG _ ' [in][out] *Effect VT_I4 <Long>
, BYREF prm_Button AS INTEGER _ ' [in][out] *Button VT_I2 <Integer>
, BYREF prm_Shift AS INTEGER _ ' [in][out] *Shift VT_I2 <Integer>
, BYREF prm_x AS SINGLE _ ' [in][out] *x VT_R4 <Single>
, BYREF prm_y AS SINGLE _ ' [in][out] *y VT_R4 <Single>
, BYREF prm_State AS INTEGER _ ' [in][out] *State VT_I2 <Integer>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
' =====================================================================================
METHOD OLEDragDrop <1555> ( _
BYREF prm_Data AS IDispatch _ ' [in][out] **Data DataObject <coclass>
, BYREF prm_Effect AS LONG _ ' [in][out] *Effect VT_I4 <Long>
, BYREF prm_Button AS INTEGER _ ' [in][out] *Button VT_I2 <Integer>
, BYREF prm_Shift AS INTEGER _ ' [in][out] *Shift VT_I2 <Integer>
, BYREF prm_x AS SINGLE _ ' [in][out] *x VT_R4 <Single>
, BYREF prm_y AS SINGLE _ ' [in][out] *y VT_R4 <Single>
) ' void
' *** Insert your code here ***
END METHOD
' =====================================================================================
END INTERFACE
END CLASS
Specifically, in fnWndProc_OnCreate(), this creates the ActiveX Control ...
hCtl=CreateWindowEx _
( _
0, _
$OC_ClassNAME, _
"MSFlexGridLib.MSFlexGrid;RTLKEY:72E67120-5959-11cf-91F6-C2863C385E30", _
%WS_CHILD OR %WS_VISIBLE, _
10, _
10, _
280, _
250, _
Wea.hWnd, _
%ID_CONTAINER, _
Wea.hInst, _
Byval %NULL _
)
The 2nd parameter of the call is the string equate $OC_ClassName, which is defined in OleCon.inc. The 3rd parameter ...
"MSFlexGridLib.MSFlexGrid;RTLKEY:72E67120-5959-11cf-91F6-C2863C385E30",
...is a string which Jose parses in the WM_CREATE handler of the Container Control based on the ';' character. The 1st substring, i.e., the left one, is the Program ID for the MSFlexGrid. The 2nd sub-string, i.e., "RTLKEY:72E67120-5959-11cf-91F6-C2863C385E30", is my Run Time License Key. You will need yours as I previously discussed. The dependency and size information for the above binary package is as follows ...
MSFlexGrid2.exe 64 K
MSFlxGrd.ocx 255 K
========================
319 K
So we have 319 K in two files as opposed to 364 K in three files with the Atl approach. But we can even do better - at least size wise. The last grid I will show you is my own - FHGrid9.dll. It is posted here at ...
http://www.jose.it-berater.org/smfforum/index.php?topic=4642.0
Its also a COM based dll, but its considerably different from MSFlxGrd.ocx. Its only 22 K and doesn't require an Active X Control Container. You can use native PowerBASIC COM calls to instantiate it, i.e., NewCom. Here is the above program but using my grid ...
'FHGrid1.bas
#Compile Exe "FHGrid1.exe"
#Dim All
%UNICODE = 1
#If %Def(%UNICODE)
Macro ZStr = WStringz
Macro BStr = WString
%SIZEOF_CHAR = 2
#Else
Macro ZStr = Asciiz
Macro BStr = String
%SIZEOF_CHAR = 1
#EndIf
$CLSID_FHGrid = GUID$("{20000000-0000-0000-0000-000000000088}")
$IID_IFHGrid = GUID$("{20000000-0000-0000-0000-000000000089}")
$IID_IGridEvents = GUID$("{20000000-0000-0000-0000-00000000008A}")
%NUMBER_ROWS = 25
%NUMBER_COLUMNS = 3
#Include "Windows.inc"
#Include "ObjBase.inc"
Type GridInterfaces
pGrid As Dword Ptr
pSink As Dword Ptr
End Type
Type WndEventArgs
wParam As Long
lParam As Long
hWnd As Dword
hInst As Dword
End Type
Declare Function FnPtr(wea As WndEventArgs) As Long
Type MessageHandler
wMessage As Long
dwFnPtr As Dword
End Type
Macro CObj(pUnk, dwAddr) = Poke Dword, Varptr(pUnk), dwAddr
Interface IGrid $IID_IFHGrid : Inherit IAutomation
Method CreateGrid _
( _
Byval hParent As Long, _
Byval strSetup As BStr, _
Byval x As Long, _
Byval y As Long, _
Byval cx As Long, _
Byval cy As Long, _
Byval iRows As Long, _
Byval iCols As Long, _
Byval iRowHt As Long, _
Byval iSelectionBackColor As Long, _
Byval iSelectionTextColor As Long, _
Byval strFontName As BStr, _
Byval iFontSize As Long, _
Byval iFontWeight As Long _
)
Method SetRowCount(Byval iRowCount As Long, Byval blnForce As Long)
Method GetRowCount() As Long
Method SetData(Byval iRow As Long, Byval iCol As Long, Byval strData As WString)
Method GetData(Byval iRow As Long, Byval iCol As Long) As WString
Method FlushData()
Method Refresh()
Method GetVisibleRows() As Long
Method GethGrid() As Long
Method GethCell(Byval iRow As Long, Byval iCol As Long) As Long
Method GethComboBox(Byval iCol As Long) As Long
Method SetCellAttributes(Byval iRow As Long, Byval iCol As Long, Byval iBackColor As Long, Byval iTextColor As Long) As Long
Method DeleteRow(Byval iRow As Long)
End Interface
Class CGridEvents As Event
Instance hMain As Dword
Interface IGridEvents $IID_IGridEvents : Inherit IAutomation
Method Grid_OnKeyPress(Byval iKeyCode As Long, Byval iKeyData As Long, Byval iRow As Long, Byval iCol As Long, Byref blnCancel As Long)
MsgBox("You Pressed A Key!")
End Method
Method Grid_OnKeyDown(Byval iKeyCode As Long, Byval iKeyData As Long, Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long, Byref blnCancel As Long)
' Insert your code here
End Method
Method Grid_OnLButtonDown(Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long)
' Insert your code here
End Method
Method Grid_OnLButtonDblClk(Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long)
MsgBox("You Double Clicked In The Grid!")
End Method
Method Grid_OnPaste(Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long)
' Insert your code here
End Method
Method Grid_OnRowSelection(Byval iRow As Long, Byval iAction As Long)
' Insert Code Here
End Method
Method Grid_OnDelete(Byval iRow As Long)
' Insert Code Here
End Method
End Interface
End Class
Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
Local pGridInterfaces As GridInterfaces Ptr
Local pCreateStruct As CREATESTRUCT Ptr
Local pSink As IGridEvents
Local strSetup As BStr
Local pGrid As IGrid
pCreateStruct=wea.lParam : wea.hInst=@pCreateStruct.hInstance
pGridInterfaces=HeapAlloc(GetProcessHeap(),%HEAP_ZERO_MEMORY,sizeof(GridInterfaces))
If pGridInterfaces=0 Then
MsgBox("Memory Allocation Failure")
Function=-1 : Exit Function
End If
Call SetWindowLong(Wea.hWnd,0,pGridInterfaces)
Let pGrid = NewCom "FHGrid9.Grid"
If IsObject(pGrid) Then
@pGridInterfaces.pGrid=Objptr(pGrid)
pGrid.AddRef()
strSetup="100:Column 1:^:edit,100:Column 2:^:edit,100:Column 3:^:edit"
pGrid.CreateGrid(Wea.hWnd,strSetup,10,10,300,300,%NUMBER_ROWS,%NUMBER_COLUMNS,20,0,0,"Times New Roman",10,%FW_LIGHT) 'was 218
If ObjResult=%S_OK Then
pSink = Class "CGridEvents"
Events From pGrid Call pSink
@pGridInterfaces.pSink=Objptr(pSink)
End If
End If
fnWndProc_OnCreate=0
End Function
Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
Local pGridInterfaces As GridInterfaces Ptr
Local pSink As IGridEvents
Local pGrid As IGrid
Local hHeap As Dword
pGridInterfaces=GetWindowLong(Wea.hWnd,0)
If pGridInterfaces Then
hHeap=GetProcessHeap()
If @pGridInterfaces.pSink Then
CObj(pSink,@pGridInterfaces.pSink)
Events End pSink : Set pSink=Nothing
End If
If @pGridInterfaces.pGrid Then
CObj(pGrid,@pGridInterfaces.pGrid)
Set pGrid=Nothing
End If
HeapFree(hHeap,0,pGridInterfaces)
End If
Call CoFreeUnusedLibraries()
Call PostQuitMessage(0)
Function=0
End Function
Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
Local Wea As WndEventArgs
Select Case As Long wMsg
Case %WM_CREATE
Wea.hWnd=hWnd: Wea.wParam=wParam: Wea.lParam=lParam
Function=fnWndProc_OnCreate(Wea) : Exit Function
Case %WM_DESTROY
Wea.hWnd=hWnd: Wea.wParam=wParam: Wea.lParam=lParam
Function=fnWndProc_OnDestroy(Wea): Exit Function
End Select
fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function
Function WinMain(ByVal hInstance As Long, ByVal hPrevIns As Long, ByVal lpCmdLn As ZStr Ptr, ByVal iShow As Long) As Long
Local szAppName As ZStr*16
Local wc As WndClassEx
Local hWnd As Dword
Local Msg As tagMsg
szAppName="Test My Grid"
wc.lpszClassName=VarPtr(szAppName) : wc.lpfnWndProc=CodePtr(fnWndProc)
wc.cbWndExtra=4 : wc.hInstance=hInstance
wc.cbSize=SizeOf(wc) : wc.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
wc.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW) : wc.hbrBackground=%COLOR_BTNFACE+1
Call RegisterClassEx(wc)
hWnd=CreateWindowEx(0,szAppName,szAppName,%WS_OVERLAPPEDWINDOW,200,100,350,360,0,0,hInstance,ByVal 0)
Call ShowWindow(hWnd,iShow)
While GetMessage(Msg,%NULL,0,0)
Call TranslateMessage(Msg)
Call DispatchMessage(Msg)
Wend
Function=msg.wParam
End Function
Believe it or not, that's it. You can use either the PowerBASIC COM Browser or Jose's Type Lib Browser if you want to generate includes for it, but the interface definitions for the incoming and outgoing interfaces are inline just above. You don't need an Active X Control Container to instantiate the grid, and you can just use PowerBASIC's NewCom. And it can be compiled exactly 'as is' using either the PowerBASIC includes or Jose's. Other than compiling the above code, all you need to do to get this working is download my FHGrid9.dll and register it with Windows like so ...
C:\Your_Project_Directory\>RegSvr32.exe FHGrid9.dll
That will add Registry entries to allow the COM subsystem of Windows to load it. Alternately, you can do Registry Free COM work by just including the dll in your project directory and using PowerBASIC's NewCom syntax to load the file directory. See NewCom in Help. You might be interested in the file sizes...
FHGrid1.exe 16 K
FHGrid9.dll 22 K
===================
38 K
Those would be using the PowerBASIC includes. Using Jose's the host is a couple K larger. Here's what you end up with if you put an MSFlxGrd.ocx on a Visual Basic 6 Form, configure it as above, and make a setup project out of it ...
MSFlexGrid2.cab 1421 K
Setup.exe 137 K
Setup.lst 4 K
========================
1562 K
So using my grid and the program above its 41 times smaller than the VB6 counterpart! Moving on, lets add code to all three of these programs I've presented so far to complete the rest of the job though. And the rest of the job is to load the Titles Table from Biblio.mdb and have the program automatically persist changes/edits back to the database. I'll work backwards from here and we'll start with the program just above using my grid, then we'll try to tackle the MSFlexGrid cases. Here again is the list of necessary steps to complete from the beginning of this tutorial ...
1) Open a database and table;
2) Determine schematics of table such as number rows, columns, column names, data types, etc;
3) Configure grid to accept this data;
4) Retrieve data from database table and populate grid;
5) Persist user edits/changes in grid back to database and table.
And just below is the modified FHGrid1.bas from just above, with the necessary changes to accomplish this. It can be compiled with either PowerBASIC's or Jose's includes. I'll discusss it in detail afterwards...
'FHGrid2.bas 'Compiles With Either PowerBASIC Or Jose Roca's Includes.
' 'Needs PB Win 10 and FHGrid9.dll, i.e., "FHGrid9.Grid"
#Compile Exe "FHGrid2"
#Dim All
#Register None
%UNICODE = 1
'%DEBUG = 1
#If %Def(%UNICODE)
Macro ZStr = WStringz
Macro BStr = WString
%SIZEOF_CHAR = 2
#Else
Macro ZStr = Asciiz
Macro BStr = String
%SIZEOF_CHAR = 1
#EndIf
'$DB_PATH = "C:\Program Files (x86)\Microsoft Visual Studio\VB98\Biblio.mdb"
$DB_PATH = "C:\Program Files\Microsoft Visual Studio\VB98\Biblio.mdb"
$DB_DRIVER = "Microsoft Access Driver (*.mdb)"
$CLSID_FHGrid = GUID$("{20000000-0000-0000-0000-000000000088}")
$IID_IFHGrid = GUID$("{20000000-0000-0000-0000-000000000089}")
$IID_IGridEvents = GUID$("{20000000-0000-0000-0000-00000000008A}")
#Include "Windows.inc"
#Include "SqlIncs.inc"
#Include "CSql.inc"
Type GridInterfaces
pGrid As Dword Ptr
pSink As Dword Ptr
End Type
Type EditFlags
iRecords As Long
pEdits As Byte Ptr
End Type
Type WndEventArgs
wParam As Long
lParam As Long
hWnd As Dword
hInst As Dword
End Type
Declare Function FnPtr(wea As WndEventArgs) As Long
Type MessageHandler
wMessage As Long
dwFnPtr As Dword
End Type
Global MsgHdlr() As MessageHandler
Macro CObj(pUnk, dwAddr) = Poke Dword, Varptr(pUnk), dwAddr
#If %Def(%Debug)
Sub Prnt(strLn As BStr)
Local iLen, iWritten As Long
Local hStdOutput As Dword
Local strNew As BStr
hStdOutput=GetStdHandle(%STD_OUTPUT_HANDLE)
strNew=strLn + $CrLf
iLen = Len(strNew)
WriteConsole(hStdOutput, Byval Strptr(strNew), iLen, iWritten, Byval 0)
End Sub
#EndIf
Interface IGrid $IID_IFHGrid : Inherit IAutomation
Method CreateGrid _
( _
Byval hParent As Long, _
Byval strSetup As BStr, _
Byval x As Long, _
Byval y As Long, _
Byval cx As Long, _
Byval cy As Long, _
Byval iRows As Long, _
Byval iCols As Long, _
Byval iRowHt As Long, _
Byval iSelectionBackColor As Long, _
Byval iSelectionTextColor As Long, _
Byval strFontName As BStr, _
Byval iFontSize As Long, _
Byval iFontWeight As Long _
)
Method SetRowCount(Byval iRowCount As Long, Byval blnForce As Long)
Method GetRowCount() As Long
Method SetData(Byval iRow As Long, Byval iCol As Long, Byval strData As WString)
Method GetData(Byval iRow As Long, Byval iCol As Long) As WString
Method FlushData()
Method Refresh()
Method GetVisibleRows() As Long
Method GethGrid() As Long
Method GethCell(Byval iRow As Long, Byval iCol As Long) As Long
Method GethComboBox(Byval iCol As Long) As Long
Method SetCellAttributes(Byval iRow As Long, Byval iCol As Long, Byval iBackColor As Long, Byval iTextColor As Long) As Long
Method DeleteRow(Byval iRow As Long)
End Interface
Class CGridEvents As Event
Instance hMain As Dword
Class Method Create()
hMain=FindWindow("Test My Grid","Test My Grid")
End Method
Interface IGridEvents $IID_IGridEvents : Inherit IAutomation
Method Grid_OnKeyPress(Byval iKeyCode As Long, Byval iKeyData As Long, Byval iRow As Long, Byval iCol As Long, Byref blnCancel As Long)
Local pEditFlags As EditFlags Ptr
pEditFlags=GetWindowLong(hMain,4)
If pEditFlags And @pEditFlags.pEdits Then
@pEditFlags.@pEdits[iRow] = @pEditFlags.@pEdits[iRow] Or 2^(iCol-1)
End If
End Method
Method Grid_OnKeyDown(Byval iKeyCode As Long, Byval iKeyData As Long, Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long, Byref blnCancel As Long)
' Insert your code here
End Method
Method Grid_OnLButtonDown(Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long)
' Insert your code here
End Method
Method Grid_OnLButtonDblClk(Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long)
' Insert Your Code Here
End Method
Method Grid_OnPaste(Byval iCellRow As Long, Byval iGridRow As Long, Byval iCol As Long)
' Insert your code here
End Method
Method Grid_OnRowSelection(Byval iRow As Long, Byval iAction As Long)
' Insert Code Here
End Method
Method Grid_OnDelete(Byval iRow As Long)
Local pGridInterfaces As GridInterfaces Ptr
Local pEditFlags As EditFlags Ptr
Local strQuery As BStr
Local strISBN As BStr
Local pGrid As IGrid
Local hStmt As Dword
Local pSql As ISql
#If %Def(%Debug)
Prnt "Entering Grid_OnDelete()"
Prnt " iRow = " & Str$(iRow)
#EndIf
MousePtr 11
pGridInterfaces=GetWindowLong(hMain,0)
If pGridInterfaces Then
If @pGridInterfaces.pGrid Then
CObj(pGrid,@pGridInterfaces.pGrid)
Call pGrid.AddRef()
pEditFlags=GetWindowLong(hMain,4)
If pEditFlags Then
Call UpdateDatabase(@pEditFlags.iRecords, @pEditFlags.pEdits, pGrid)
pSql=Class "CSql"
pSql.strDBQ=$DB_PATH
pSql.strDriver=$DB_DRIVER
Call pSql.ODBCConnect()
If pSql.blnConnected Then
#If %Def(%Debug)
Prnt " Got In Where pSQl.blnConnected = True!"
#EndIf
Call SQLAllocHandle(%SQL_HANDLE_STMT,pSql.hConn(),hStmt)
strISBN=pGrid.GetData(iRow,3)
strQuery="DELETE FROM Titles Where ISBN=" & Chr$(39) & strISBN & Chr$(39) & ";"
#If %Def(%Debug)
Prnt " " & strQuery
#EndIf
Call SQLExecDirect(hStmt,Byval Strptr(strQuery),%SQL_NTS)
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Call pSQL.ODBCDisconnect()
Call pGrid.DeleteRow(iRow)
Call pGrid.Refresh()
End If
End If
End If
End If
MousePtr 1
#If %Def(%Debug)
Prnt "Leaving Grid_OnDelete()"
#EndIf
End Method
End Interface
End Class
Function blnGetRecordCount(Byref Sql As ISql, Byref iRecCt As Long) As Long
Local szQuery As ZStr*64
Local hStmt As Dword
Local iJnk As Long
szQuery="SELECT Count(*) As RecordCount FROM Titles"
Call SQLAllocHandle(%SQL_HANDLE_STMT,Sql.hConn(),hStmt)
Call SQLBindCol(hStmt,1,%SQL_C_ULONG,iRecCt,0,iJnk)
Call SQLExecDirect(hStmt,szQuery,%SQL_NTS)
Call SQLFetch(hStmt)
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
If iRecCt Then
Function=%True
Else
Function=%False
End If
End Function
Function blnLoadTitles(Byref Sql As ISql, Byref pGrid As IGrid) As Long
Local szQuery As ZStr * 256
Local szTitle As ZStr * 256
Local szISBN As ZStr * 24
Local iYrPub As Integer
Local iPubID As Long
Local szDescription As ZStr * 56
Local szNotes As ZStr * 56
Local szSubject As ZStr * 56
Local szComments As ZStr * 256
Local iReturn As Long
Local hStmt As Dword
Local iLen() As Long
Register i As Long
#If %Def(%Debug)
Prnt " Entering blnLoadTitles()"
#Endif
Redim iLen(8) As Long
szQuery = "SELECT Title, [Year Published], ISBN, PubID, Description, Notes, Subject, Comments FROM Titles;
Call SQLAllocHandle(%SQL_HANDLE_STMT,Sql.hConn(),hStmt)
Call SQLBindCol(hStmt,1,%SQL_C_WCHAR,szTitle,510,iLen(1)) ' In using ODBC one declares a variable for
Call SQLBindCol(hStmt,2,%SQL_C_SHORT,iYrPub,0,iLen(2)) ' each field being retrieved from the data
Call SQLBindCol(hStmt,3,%SQL_C_WCHAR,szISBN,46,iLen(3)) ' source. The address of this variable is
Call SQLBindCol(hStmt,4,%SQL_C_LONG,iPubID,0,iLen(4)) ' given to the db driver in SQLBindCol()
Call SQLBindCol(hStmt,5,%SQL_C_WCHAR,szDescription,110,iLen(5)) ' calls - one for each field/column. Then
Call SQLBindCol(hStmt,6,%SQL_C_WCHAR,szNotes,110,iLen(6)) ' one calls SQLExecDirect() to retrieve a
Call SQLBindCol(hStmt,7,%SQL_C_WCHAR,szSubject,110,iLen(7)) ' database cursor. It is through this data-
Call SQLBindCol(hStmt,8,%SQL_C_WCHAR,szComments,510,iLen(8)) ' base cursor one loops with calls of
iReturn=SQLExecDirect(hStmt,szQuery,%SQL_NTS) ' SQLFetch() to retrieve a row of data into
If iReturn=%SQL_SUCCESS Or iReturn=%SQL_SUCCESS_WITH_INFO Then ' the bound variables bound with SQLBindCol().
i=1 ' When the SQLFetch() call is made, those
Do While SQLFetch(hStmt)<>%SQL_NO_DATA ' iLen() variables seen in the last para-
If iLen(1) Then pGrid.SetData(i,1,szTitle) ' meter of the SQLBindCol() calls receive the byte
If iLen(2) Then pGrid.SetData(i,2,Str$(iYrPub)) ' count of data read out of the row from the database
If iLen(3) Then pGrid.SetData(i,3,szISBN) ' cursor. If a zero ends up in there it means that
If iLen(4) Then pGrid.SetData(i,4,Str$(iPubID)) ' for the respective field that field was NULL. How-
If iLen(5) Then pGrid.SetData(i,5,szDescription) ' ever, that variable may and almost certainly is
If iLen(6) Then pGrid.SetData(i,6,szNotes) ' holding whatever was put there from a previous call
If iLen(7) Then pGrid.SetData(i,7,szSubject) ' of SQLFetch(). So if you use that data from the
If iLen(8) Then pGrid.SetData(i,8,szComments) ' bound variable when the corresponding iLen(i)
Incr i ' variable is telling you nothing was read, you are
Loop ' going to get yourself into trouble. That's why
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt) ' I'm checking every iLen(i) before I write the
Else ' bound variable's data into the grid.
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Erase iLen()
Function=%False : Exit Function
End If
pGrid.Refresh()
Erase iLen()
#If %Def(%Debug)
Prnt " " & szQuery
Prnt " Leaving blnLoadTitles()"
#Endif
Function=%True
End Function
Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long ' Offset What's Stored There
Local pGridInterfaces As GridInterfaces Ptr ' ===============================
Local pCreateStruct As CREATESTRUCT Ptr ' 0 - 3 pGridInterfaces
Local pEditFlags As EditFlags Ptr ' 4 - 7 pEditFlags
Local pSink As IGridEvents
Local iRecordCount As Long
Local strSetup As BStr
Local pGrid As IGrid
Local hHeap As Dword
Local pSql As ISql
#If %Def(%Debug)
Call AllocConsole()
Prnt "Entering fnWndProc_OnCreate()"
#EndIf
pCreateStruct=wea.lParam : wea.hInst=@pCreateStruct.hInstance
hHeap=GetProcessHeap()
pGridInterfaces=HeapAlloc(hHeap,%HEAP_ZERO_MEMORY,sizeof(GridInterfaces))
If pGridInterfaces Then
Call SetWindowLong(Wea.hWnd,0,pGridInterfaces)
pGrid = NewCom "FHGrid9.Grid"
If IsObject(pGrid) Then
@pGridInterfaces.pGrid=Objptr(pGrid)
pGrid.AddRef()
pSql=Class "CSql"
pSql.strDBQ=$DB_PATH
pSql.strDriver=$DB_DRIVER
Call pSql.ODBCConnect()
If pSql.blnConnected Then
If blnGetRecordCount(pSql, iRecordCount) Then
#If %Def(%Debug)
Prnt " iRecordCount = " & Str$(iRecordCount)
#EndIf
iRecordCount=iRecordCount*1.01
hHeap=GetProcessHeap()
pEditFlags=HeapAlloc(hHeap,%HEAP_ZERO_MEMORY,sizeof(EditFlags))
#If %Def(%Debug)
Prnt " iRecordCount = " & Str$(iRecordCount)
Prnt " pEditFlags = " & Str$(pEditFlags)
#EndIf
If pEditFlags Then
@pEditFlags.iRecords=iRecordCount
@pEditFlags.pEdits=HeapAlloc(hHeap,%HEAP_ZERO_MEMORY,iRecordCount+1)
#If %Def(%Debug)
Prnt " @pEditFlags.iRecords = " & Str$(@pEditFlags.iRecords)
Prnt " @pEditFlags.pEdits = " & Str$(@pEditFlags.pEdits)
#EndIf
If @pEditFlags.pEdits Then
SetWindowLong(Wea.hWnd,4,pEditFlags)
strSetup= _
"300:Title:^:edit," & _
"200:Year Published:^:edit," & _
"150:ISBN:^:edit," & _
"90:PubID:^:edit," & _
"200:Description:^:edit," & _
"90:Notes:^:edit," & _
"100:Subject:^:edit," & _
"110:Comments:^:edit"
pGrid.CreateGrid(Wea.hWnd,strSetup,10,10,850,500,iRecordCount,8,20,0,0,"Times New Roman",12,%FW_LIGHT)
If ObjResult=%S_OK Then
pSink = Class "CGridEvents"
Events From pGrid Call pSink
@pGridInterfaces.pSink=Objptr(pSink)
Call blnLoadTitles(pSql, pGrid)
End If
End If
End If
End If
pSql.ODBCDisconnect()
End If
Else
MsgBox("Couldn't Create FHGrid9!")
Function=-1 : Exit Function
End If
Else
MsgBox("Memory Allocation Failure")
Function=-1 : Exit Function
End If
#If %Def(%Debug)
Prnt "Leaving fnWndProc_OnCreate()" & $CrLf
#EndIf
fnWndProc_OnCreate=0
End Function
Function blnUpdateRecord(Byval iRecord As Long, Byval pRecord As Byte Ptr, Byref Sql As ISql, Byref pGrid As IGrid) As Long
Local strQuery, strField, strPrimaryKey As BStr
Local iReturn As Long
Local hStmt As Dword
Register i As Long
#If %Def(%Debug)
Prnt ""
Prnt " Entering blnUpdateRecord()"
Prnt " Record #" & Str$(iRecord) & " Was Edited"
Prnt " @pRecord = " & Str$(@pRecord)
Prnt ""
#EndIf
strQuery="UPDATE Titles SET " ' In this code we loop through the bits at @pRecord looking
For i=0 To 7 ' for any that have been set in Grid_OnKeyPress(). We use
If IsTrue(@pRecord And 2^i) Then ' the bitwise And operator for that. An And operation against
Select Case As Long i ' a set bit will return true. So the loop will And 1 against
Case 0 ' @pRecord, then 2, then 4, then 8, then 16, etc. When we
strField=pGrid.GetData(iRecord,1) ' make a hit we concatenate that respective string into
If InStr(1,strField,Chr$(39)) Then ' strQuery, and collect the data from the grid cell for that
Replace Chr$(39) With "''" In strField ' column and row.
End If
strQuery = strQuery & "Title=" & Chr$(39) & strField & Chr$(39) & ","
Case 1
strField=pGrid.GetData(iRecord,2)
strQuery = strQuery & "[Year Published]=" & strField & ","
Case 3
strField=pGrid.GetData(iRecord,4)
strQuery = strQuery & "PubID=" & strField & ","
Case 4
strField=pGrid.GetData(iRecord,5)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Description=" & Chr$(39) & strField & Chr$(39) & ","
Case 5
strField=pGrid.GetData(iRecord,6)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Notes=" & Chr$(39) & strField & Chr$(39) & ","
Case 6
strField=pGrid.GetData(iRecord,7)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Subject=" & Chr$(39) & strField & Chr$(39) & ","
Case 7
strField=pGrid.GetData(iRecord,8)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Comments=" & Chr$(39) & strField & Chr$(39) & ","
End Select
End If
Next i
strQuery=Left$(strQuery,Len(strQuery)-1)
strPrimaryKey=" WHERE ISBN=" & Chr$(39) & pGrid.GetData(iRecord,3) & Chr$(39) & ";"
strQuery=strQuery+strPrimaryKey
#If %Def(%Debug)
Prnt " strQuery = " & strQuery
#EndIf
Call SQLAllocHandle(%SQL_HANDLE_STMT,Sql.hConn(),hStmt)
iReturn=SQLExecDirect(hStmt,Byval Strptr(strQuery),%SQL_NTS)
If iReturn<>%SQL_SUCCESS And iReturn<>%SQL_SUCCESS_WITH_INFO Then
Sql.ODBCGetDiagRec(hStmt)
#If %Def(%Debug)
Prnt " iReturn = " & Str$(iReturn)
Prnt " %SQL_SUCCESS = " & Str$(%SQL_SUCCESS)
Prnt " %SQL_SUCCESS_WITH_INFO = " & Str$(%SQL_SUCCESS_WITH_INFO)
Prnt " Sql.iNativeErrCode = " & Str$(Sql.iNativeErrCode)
Prnt " Sql.strErrMsg = " & Sql.strErrMsg
Prnt " Sql.strErrCode = " & Sql.strErrCode
#EndIf
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
#If %Def(%Debug)
Prnt " Leaving blnUpdateRecord()"
#EndIf
Function=%False : Exit Function
End If
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
#If %Def(%Debug)
Prnt " Leaving blnUpdateRecord()"
#EndIf
Function=%True
End Function
Function blnInsertRecord(Byval iRecord As Long, Byval pRecord As Byte Ptr, Byref Sql As ISql, Byref pGrid As IGrid) As Long
Local strQuery, strField As BStr
Local iReturn As Long
Local hStmt As Dword
Register i As Long
#If %Def(%Debug)
Prnt $CrLf
Prnt " Entering blnInsertRecord()"
Prnt " Record #" & Str$(iRecord) & " Was Edited"
Prnt " @pRecord = " & Str$(@pRecord)
Prnt $CrLf
#EndIf
strQuery="INSERT INTO Titles (" ' This is exactly like blnUpdateRecord() above in its logic, but
For i=0 To 7 ' we're constructing an SQL INSERT statement here. We loop through
If IsTrue(@pRecord And 2^i) Then ' all the bits in the record passed in as a parameter and search for
Select Case As Long i ' dirty bits. When we find one we add the field name to the INSERT
Case 0 ' statement, and get the associated data from the grid for whatever
strQuery=strQuery+"Title," ' column/field we made the 'hit'. When we're done we call
Case 1 ' SQLExecDirect() to see if we can get the record in.
strQuery=strQuery+"[Year Published],"
Case 2
strQuery=strQuery+"ISBN,"
Case 3
strQuery=strQuery+"PubID,"
Case 4
strQuery=strQuery+"Description,"
Case 5
strQuery=strQuery+"Notes,"
Case 6
strQuery=strQuery+"Subject,"
Case 7
strQuery=strQuery+"Comments,"
End Select
End If
Next i
strQuery=Left$(strQuery,Len(strQuery)-1)+") VALUES ("
For i=0 To 7
If IsTrue(@pRecord And 2^i) Then
Select Case As Long i
Case 0
strField=pGrid.GetData(iRecord,1)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 1
strField=pGrid.GetData(iRecord,2)
strQuery = strQuery & strField & ","
Case 2
strField=pGrid.GetData(iRecord,3)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 3
strField=pGrid.GetData(iRecord,4)
strQuery = strQuery & strField & ","
Case 4
strField=pGrid.GetData(iRecord,5)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 5
strField=pGrid.GetData(iRecord,6)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 6
strField=pGrid.GetData(iRecord,7)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 7
strField=pGrid.GetData(iRecord,8)
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
End Select
End If
Next i
strQuery=Left$(strQuery,Len(strQuery)-1) & ");"
#If %Def(%Debug)
Prnt " strQuery = " & strQuery
#EndIf
Call SQLAllocHandle(%SQL_HANDLE_STMT,Sql.hConn(),hStmt)
iReturn=SQLExecDirect(hStmt,Byval Strptr(strQuery),%SQL_NTS)
If iReturn<>%SQL_SUCCESS And iReturn<>%SQL_SUCCESS_WITH_INFO Then
Sql.ODBCGetDiagRec(hStmt)
#If %Def(%Debug)
Prnt " iReturn = " & Str$(iReturn)
Prnt " %SQL_SUCCESS = " & Str$(%SQL_SUCCESS)
Prnt " %SQL_SUCCESS_WITH_INFO = " & Str$(%SQL_SUCCESS_WITH_INFO)
Prnt " Sql.iNativeErrCode = " & Str$(Sql.iNativeErrCode)
Prnt " Sql.strErrMsg = " & Sql.strErrMsg
Prnt " Sql.strErrCode = " & Sql.strErrCode
#Else
iReturn=MsgBox(Sql.strErrMsg, %MB_ICONERROR, "I Don't Want To Sugar Coat It ...")
#EndIf
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Function=%False : Exit Function
End If
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
#If %Def(%Debug)
Prnt " Leaving blnInsertRecord()"
Prnt $CrLf
#EndIf
Function=%True
End Function
Sub UpdateDatabase(Byval iRecords As Long, Byval pEdits As Byte Ptr, Byref pGrid As IGrid)
Local blnDataEdited, iReturn As Long
Register i As Long
Local Sql As ISql
#If %Def(%Debug)
Prnt " Entering UpdateDatabase()"
Prnt " iRecords = " & Str$(iRecords)
Prnt " pEdits = " & Str$(pEdits)
#EndIf
For i = 1 To iRecords ' If @pEdit[i] is anything other than zero, we know the user
If @pEdits[i] Then ' pressed a key while the caret was in some cell. Therefore,
blnDataEdited=%True ' something was edited or inserted. In that case we're going
Exit For ' to have to get inside the If just below and see just what
End If ' the user did. Every record (byte at @pEdits[i]) will have
Next i ' to be tested for a 'dirty' bit or bits. When we find a
If blnDataEdited Then ' non-zero byte, we'll pass that byte and record number to
Sql=Class "CSql" ' blnUpdateRecord() to see if an UPDATE Query will update
Sql.strDBQ=$DB_PATH ' that record. It might fail. For example, it would
Sql.strDriver=$DB_DRIVER ' fail if the user added a new record to the end of the
Call Sql.ODBCConnect() ' grid's pre-existing data. In that case an INSERT Query
If Sql.blnConnected Then ' might do the trick. So we then try blnInsertRecord().
#If %Def(%Debug)
Prnt " Sql.blnConnected = True!"
#Endif
For i=1 To iRecords ' If that fails we simply give up and notify the user that
If @pEdits[i] Then ' his money will be refunded and we give up.
If IsFalse(blnUpdateRecord(i,Varptr(@pEdits[i]),Sql,pGrid)) Then
If IsFalse(blnInsertRecord(i,Varptr(@pEdits[i]),Sql,pGrid)) Then
iReturn=MsgBox _
( _
"Failed To Update/Insert Record #" & Str$(i) & "!", _
%MB_ICONERROR, _
"I Don't Want To Sugar Coat It!" _
)
End If ' What blnUpdateRecord() and blnInsertRecord() do is construct
End If ' either an UPDATE or INSERT Query from the 'dirty' bits
@pEdits[i]=0 ' found at @pEdit[i]. So its basically a string concat-
End If ' enation job. Note that Sql was passed to there from here,
Next i ' and whatever the outcome was, we close it here.
Sql.ODBCDisconnect()
End If
End If
#If %Def(%Debug)
Prnt " Leaving UpdateDatabase()"
#EndIf
End Sub
Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
Local pGridInterfaces As GridInterfaces Ptr
Local pEditFlags As EditFlags Ptr
Local pSink As IGridEvents
Local pGrid As IGrid
Local hHeap As Dword
Local bFree As Long
#If %Def(%Debug)
Prnt "Entering fnWndProc_OnDestroy()"
#EndIf
pGridInterfaces=GetWindowLong(Wea.hWnd,0)
If pGridInterfaces Then
If @pGridInterfaces.pSink Then
CObj(pSink,@pGridInterfaces.pSink)
Events End pSink : Set pSink=Nothing
End If
If @pGridInterfaces.pGrid Then
CObj(pGrid,@pGridInterfaces.pGrid)
pGrid.FlushData()
hHeap=GetProcessHeap()
pEditFlags=GetWindowLong(Wea.hWnd,4)
If pEditFlags Then
#If %Def(%Debug)
Prnt " pEditFlags = " & Str$(pEditFlags)
Prnt " @pEditFlags.iRecords = " & Str$(@pEditFlags.iRecords)
#EndIf
If @pEditFlags.pEdits Then
#If %Def(%Debug)
Prnt " @pEditFlags.pEdits = " & Str$(@pEditFlags.pEdits)
#EndIf
Call UpdateDatabase(@pEditFlags.iRecords, @pEditFlags.pEdits,pGrid)
bFree=HeapFree(hHeap,0,@pEditFlags.pEdits)
#If %Def(%Debug)
Prnt " bFree(@pEditFlags.pEdits) = " & Str$(bFree)
#EndIf
End If
bFree=HeapFree(hHeap,0,pEditFlags)
#If %Def(%Debug)
Prnt " bFree(pEditFlags) = " & Str$(bFree)
#EndIf
End If
Set pGrid=Nothing
End If
bFree=HeapFree(hHeap,0,pGridInterfaces)
End If
Call CoFreeUnusedLibraries()
Call PostQuitMessage(0)
#If %Def(%Debug)
Prnt "Leaving fnWndProc_OnDestroy()"
#EndIf
Function=0
End Function
Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
Local wea As WndEventArgs
Register iReturn As Long
Register i As Long
For i=0 To 1
If wMsg=MsgHdlr(i).wMessage Then
wea.hWnd=hWnd: wea.wParam=wParam: wea.lParam=lParam
Call Dword MsgHdlr(i).dwFnPtr Using FnPtr(wea) To iReturn
fnWndProc=iReturn
Exit Function
End If
Next i
fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function
Sub AttachMessageHandlers()
ReDim MsgHdlr(1) As MessageHandler 'Associate Windows Message With Message Handlers
MsgHdlr(0).wMessage=%WM_CREATE : MsgHdlr(0).dwFnPtr=CodePtr(fnWndProc_OnCreate)
MsgHdlr(1).wMessage=%WM_DESTROY : MsgHdlr(1).dwFnPtr=CodePtr(fnWndProc_OnDestroy)
End Sub
Function WinMain(ByVal hInstance As Long, ByVal hPrevIns As Long, ByVal lpCmdLn As ZStr Ptr, ByVal iShow As Long) As Long
Local szAppName As ZStr*16
Local wc As WndClassEx
Local hWnd As Dword
Local Msg As tagMsg
szAppName="Test My Grid" : Call AttachMessageHandlers()
wc.lpszClassName=VarPtr(szAppName) : wc.lpfnWndProc=CodePtr(fnWndProc)
wc.cbWndExtra=8 : wc.hInstance=hInstance
wc.cbSize=SizeOf(wc) : wc.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
wc.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW) : wc.hbrBackground=%COLOR_BTNFACE+1
Call RegisterClassEx(wc)
hWnd=CreateWindowEx(0,szAppName,szAppName,%WS_OVERLAPPEDWINDOW,200,100,880,570,0,0,hInstance,ByVal 0)
Call ShowWindow(hWnd,iShow)
While GetMessage(Msg,%NULL,0,0)
Call TranslateMessage(Msg)
Call DispatchMessage(Msg)
Wend
#If %Def(%Debug)
MsgBox("Come And Get It Before I Throw It Out!")
#EndIf
Function=msg.wParam
End Function
Here would be SqlIncs.inc...
'SqlIncs.inc
%SQL_HANDLE_ENV = 1
%SQL_HANDLE_DBC = 2
%SQL_HANDLE_STMT = 3
%SQL_NULL_HANDLE = 0&
%SQL_ATTR_ODBC_VERSION = 200
%SQL_OV_ODBC3 = 3???
%SQL_IS_POINTER = -4
%SQL_IS_UINTEGER = -5
%SQL_IS_INTEGER = -6
%SQL_IS_USMALLINT = -7
%SQL_IS_SMALLINT = -8
%SQL_DRIVER_NOPROMPT = 0
%SQL_DRIVER_COMPLETE = 1
%SQL_DRIVER_PROMPT = 2
%SQL_SUCCESS = 0
%SQL_SUCCESS_WITH_INFO = 1
%SQL_NO_DATA = 100
%SQL_ERROR = -1
%SQL_INVALID_HANDLE = -2
%SQL_STILL_EXECUTING = 2
%SQL_NEED_DATA = 99
%SQL_NTS = -3
%SQL_CHAR = 1 'sql.h
%SQL_NUMERIC = 2 'sql.h
%SQL_DECIMAL = 3 'sql.h
%SQL_INTEGER = 4 'sql.h
%SQL_SMALLINT = 5 'sql.h
%SQL_FLOAT = 6 'sql.h
%SQL_REAL = 7 'sql.h
%SQL_DOUBLE = 8 'sql.h
%SQL_C_CHAR = %SQL_CHAR 'sqlext.h
%SQL_C_LONG = %SQL_INTEGER 'sqlext.h
%SQL_C_SHORT = %SQL_SMALLINT 'sqlext.h
%SQL_C_FLOAT = %SQL_REAL 'sqlext.h
%SQL_C_DOUBLE = %SQL_DOUBLE 'sqlext.h
%SQL_TINYINT = -6
%SQL_WCHAR = -8 'sqlucode.h
%SQL_WVARCHAR = -9 'sqlucode.h
%SQL_WLONGVARCHAR = -10 'sqlucode.h
%SQL_C_WCHAR = %SQL_WCHAR 'sqlucode.h
%SQL_SIGNED_OFFSET = -20 'sqlext.h
%SQL_UNSIGNED_OFFSET = -22 'sqlext.h
%SQL_PARAM_INPUT = 1 'sqlext.h for SQLBindParameter
%SQL_C_TINYINT = %SQL_TINYINT
%SQL_C_SLONG = (%SQL_C_LONG+%SQL_SIGNED_OFFSET)
%SQL_C_SSHORT = (%SQL_C_SHORT+%SQL_SIGNED_OFFSET)
%SQL_C_STINYINT = (%SQL_TINYINT+%SQL_SIGNED_OFFSET)
%SQL_C_ULONG = (%SQL_C_LONG+%SQL_UNSIGNED_OFFSET)
%SQL_C_USHORT = (%SQL_C_SHORT+%SQL_UNSIGNED_OFFSET)
%SQL_C_UTINYINT = (%SQL_TINYINT+%SQL_UNSIGNED_OFFSET)
%SQL_TYPE_DATE = 91
%SQL_TYPE_TIME = 92
%SQL_TYPE_TIMESTAMP = 93
%SQL_C_TYPE_DATE = %SQL_TYPE_DATE
'SQLInstallerError code
%ODBC_ERROR_GENERAL_ERR = 1
%ODBC_ERROR_INVALID_BUFF_LEN = 2
%ODBC_ERROR_INVALID_HWND = 3
%ODBC_ERROR_INVALID_STR = 4
%ODBC_ERROR_INVALID_REQUEST_TYPE = 5
%ODBC_ERROR_COMPONENT_NOT_FOUND = 6
%ODBC_ERROR_INVALID_NAME = 7
%ODBC_ERROR_INVALID_KEYWORD_VALUE = 8
%ODBC_ERROR_INVALID_DSN = 9
%ODBC_ERROR_INVALID_INF = 10
%ODBC_ERROR_REQUEST_FAILED = 11
%ODBC_ERROR_INVALID_PATH = 12
%ODBC_ERROR_LOAD_LIB_FAILED = 13
%ODBC_ERROR_INVALID_PARAM_SEQUENCE = 14
%ODBC_ERROR_INVALID_LOG_FILE = 15
%ODBC_ERROR_USER_CANCELED = 16
%ODBC_ERROR_USAGE_UPDATE_FAILED = 17
%ODBC_ERROR_CREATE_DSN_FAILED = 18
%ODBC_ERROR_WRITING_SYSINFO_FAILED = 19
%ODBC_ERROR_REMOVE_DSN_FAILED = 20
%ODBC_ERROR_OUT_OF_MEM = 21
%ODBC_ERROR_OUTPUT_STRING_TRUNCATED = 22
'SQLConfigDataSource request flags
%ODBC_ADD_DSN = 1
%ODBC_CONFIG_DSN = 2
%ODBC_REMOVE_DSN = 3
%ODBC_ADD_SYS_DSN = 4
%ODBC_CONFIG_SYS_DSN = 5
%ODBC_REMOVE_SYS_DSN = 6
#If %Def(%UNICODE)
%SQL_C_TCHAR = %SQL_C_WCHAR
#else
%SQL_C_TCHAR = %SQL_C_CHAR
#EndIf
Type tagDATE_STRUCT
year As Integer
month As Word
day As Word
End Type
Type tagTIMESTAMP_STRUCT
year As Integer
month As Word
day As Word
hour As Word
minute As Word
second As Word
fraction As Dword
End Type
Declare Function SQLConfigDataSourceA Import "Odbccp32.dll" Alias "SQLConfigDataSource" _
( _
ByVal hParnt As Dword, _
ByVal iReqst As Word, _
szDriver As Asciiz, _
szAttr As Asciiz _
) As Integer
Declare Function SQLConfigDataSourceW Import "Odbccp32.dll" Alias "SQLConfigDataSourceW" _
( _
ByVal hParnt As Dword, _
ByVal iReqst As Word, _
szDriver As WStringz, _
szAttr As WStringz _
) As Integer
Declare Function SQLInstallerErrorA Lib "Odbccp32.dll" Alias "SQLInstallerError" _
( _
ByVal iErr As Word, _
ByRef pErrCode As Dword, _
ByRef szErrMsg As Asciiz, _
ByVal cbMsgBuffer As Word, _
ByRef cbRet As Word _
) As Integer
Declare Function SQLInstallerErrorW Lib "ODBCCP32.DLL" Alias "SQLInstallerErrorW" _
( _
ByVal iErr As Word, _
ByRef pErrCode As Dword, _
ByRef szErrMsg As WStringz, _
ByVal cbMsgBuffer As Word, _
ByRef cbRet As Word _
) As Integer
Declare Function SQLAllocHandle Import "Odbc32.dll" Alias "SQLAllocHandle" _
( _
Byval HandleType As Integer, _ ' SQLSMALLINT HandleType
Byval InputHandle As Dword, _ ' SQLHANDLE InputHandle
Byref OutputHandle As Dword _ ' SQLHANDLE* OutputHandle
) As Integer ' SQLRETURN
Declare Function SQLSetEnvAttr Import "Odbc32.dll" Alias "SQLSetEnvAttr" _
( _
Byval EnvironmentHandle As Dword, _ ' SQLHENV EnvironmentHandle
Byval Attribute As Long, _ ' SQLINTEGER Attribute
Byref Value As Any, _ ' SQLPOINTER Value
Byval StringLength As Long _ ' SQLINTEGER StringLength
) As Integer ' SQLRETURN
Declare Function SQLDriverConnectA Import "Odbc32.dll" Alias "SQLDriverConnect" _
( _
Byval hdbc As Dword, _ ' SQLHDBC hdbc
Byval hWnd As Dword,_ ' SQLHWND hwnd
Byref szConnStrIn As Asciiz, _ ' SQLCHAR* szConnStrIn
Byval cbConnStrIn As Integer, _ ' SQLSMALLINT cbConnStrIn
Byref szConnStrOut As Asciiz, _ ' SQLCHAR* szConnStrOut
Byval cbConnStrOutMax As Integer, _ ' SQLSMALLINT cbConnStrOutMax
Byref pcbConnStrOut As Integer, _ ' SQLSMALLINT* pcbConnStrOut
Byval fDriverCompletion As Word _ ' SQLUSMALLINT fDriverCompletion
) As Integer ' SQLRETURN
Declare Function SQLDriverConnectW Import "Odbc32.dll" Alias "SQLDriverConnectW" _
( _
Byval hdbc As Dword, _ ' SQLHDBC hdbc
Byval hwnd As Dword, _ ' SQLHWND hwnd
Byref szConnStrIn As WStringz, _ ' SQLWCHAR* szConnStrIn
Byval cbConnStrIn As Integer, _ ' SQLSMALLINT cbConnStrIn
Byref szConnStrOut As WStringz, _ ' SQLWCHAR* szConnStrOut
Byval cbConnStrOutMax As Integer, _ ' SQLSMALLINT cbConnStrOutMax
Byref pcbConnStrOut As Integer, _ ' SQLSMALLINT* pcbConnStrOut
Byval fDriverCompletion As Word _ ' SQLUSMALLINT fDriverCompletion
) As Integer ' SQLRETURN
Declare Function SQLPrepareA Import "Odbc32.dll" Alias "SQLPrepare" _
( _
Byval StatementHandle As Dword, _ ' SQLHSTMT StatementHandle
Byref StatementText As Asciiz, _ ' SQLCHAR* StatementText
Byval TextLength As Long _ ' SQLINTEGER TextLength
) As Integer ' SQLRETURN
Declare Function SQLPrepareW Import "Odbc32.dll" Alias "SQLPrepareW" _
( _
Byval StatementHandle As Dword, _ ' SQLHSTMT StatementHandle
Byref StatementText As WStringz, _ ' SQLWCHAR* szSqlStr
Byval TextLength As Long _ ' SQLINTEGER TextLength
) As Integer ' SQLRETURN
Declare Function SQLBindParameter Import "Odbc32.dll" Alias "SQLBindParameter" _
( _
Byval hstmt As Dword, _ ' SQLHSTMT hstmt
Byval ipar As Word, _ ' SQLUSMALLINT ipar
Byval fParamType As Integer, _ ' SQLSMALLINT fParamType
Byval fCType As Integer, _ ' SQLSMALLINT fCType
Byval fSqlType As Integer, _ ' SQLSMALLINT fSqlType
Byval cbColDef As Dword, _ ' SQLULEN cbColDef
Byval ibScale As Integer, _ ' SQLSMALLINT ibScale
Byref rgbValue As Any, _ ' SQLPOINTER rgbValue
Byval cbValueMax As Long, _ ' SQLLEN cbValueMax
Byref pcbValue As Long _ ' SQLLEN* pcbValue
) As Integer ' SQLRETURN
Declare Function SQLExecute Import "Odbc32.dll" Alias "SQLExecute" _
( _
Byval StatementHandle As Dword _ ' SQLHSTMT StatementHandle
) As Integer ' SQLRETURN
Declare Function SQLExecDirectA Import "Odbc32.dll" Alias "SQLExecDirect" _
( _
Byval StatementHandle As Dword, _ ' SQLHSTMT StatementHandle
Byref StatementText As Asciiz, _ ' SQLCHAR* StatementText
Byval TextLength As Long _ ' SQLINTEGER TextLength
) As Integer ' SQLRETURN
Declare Function SQLExecDirectW Import "Odbc32.dll" Alias "SQLExecDirectW" _
( _
Byval hstmt As Dword, _ ' SQLHSTMT hstmt
Byref szSqlStr As WStringz, _ ' SQLWCHAR* szSqlStr
Byval cbSqlStr As Long _ ' SQLINTEGER cbSqlStr
) As Integer ' SQLRETURN
Declare Function SQLBindCol Import "Odbc32.dll" Alias "SQLBindCol" _
( _
Byval StatementHandle As Dword, _ ' SQLHSTMT StatementHandle
Byval ColumnNumber As Integer, _ ' SQLUSMALLINT ColumnNumber
Byval TargetType As Integer, _ ' SQLSMALLINT TargetType
Byref TargetValue As Any, _ ' SQLPOINTER TargetValue
Byval BufferLength As Long, _ ' SQLLEN BufferLength
Byref StrLen_or_Ind As Long _ ' SQLLEN* StrLen_or_Ind
) As Integer ' SQLRETURN
Declare Function SQLFetch Import "Odbc32.dll" Alias "SQLFetch" _
( _
Byval StatementHandle As Dword _ ' SQLHSTMT StatementHandle
) As Integer ' SQLRETURN
Declare Function SQLGetDiagRecA Import "Odbc32.dll" Alias "SQLGetDiagRec" _
( _
Byval HandleType As Integer, _ ' SQLSMALLINT HandleType
Byval Handle As Dword, _ ' SQLHANDLE Handle
Byval RecNumber As Integer, _ ' SQLSMALLINT RecNumber
Byref Sqlstate As Asciiz, _ ' SQLCHAR* Sqlstate
Byref NativeError As Long, _ ' SQLINTEGER* NativeError
Byref MessageText As Asciiz, _ ' SQLCHAR* MessageText
Byval BufferLength As Integer, _ ' SQLSMALLINT BufferLength
Byref TextLength As Integer _ ' SQLSMALLINT* TextLength
) As Integer ' SQLRETURN
Declare Function SQLGetDiagRecW Import "Odbc32.dll" Alias "SQLGetDiagRecW" _
( _
Byval fHandleType As Integer, _ ' SQLSMALLINT fHandleType
Byval handle As Dword, _ ' SQLHANDLE handle
Byval iRecord As Integer, _ ' SQLSMALLINT iRecord
Byref szSqlState As WStringz, _ ' SQLWCHAR* szSqlState
Byref pfNativeError As Long, _ ' SQLINTEGER* pfNativeError
Byref szErrorMsg As WStringz, _ ' SQLWCHAR* szErrorMsg
Byval cbErrorMsgMax As Integer, _ ' SQLSMALLINT cbErrorMsgMax
Byref pcbErrorMsg As Integer _ ' SQLSMALLINT* pcbErrorMsg
) As Integer ' SQLRETURN
Declare Function SQLDisconnect Import "Odbc32.dll" Alias "SQLDisconnect" _
( _
Byval ConnectionHandle As Dword _ ' SQLHDBC ConnectionHandle
) As Integer ' SQLRETURN
Declare Function SQLCloseCursor Import "Odbc32.dll" Alias "SQLCloseCursor" _
( _
Byval StatementHandle As Dword _ ' SQLHSTMT StatementHandle
) As Integer ' SQLRETURN
Declare Function SQLFreeHandle Import "Odbc32.dll" Alias "SQLFreeHandle" _
( _
Byval HandleType As Integer, _ ' SQLSMALLINT HandleType
Byval Handle As Dword _ ' SQLHANDLE Handle
) As Integer ' SQLRETURN
#If %Def(%UNICODE)
Macro SQLConfigDataSource = SQLConfigDataSourceW
Macro SQLInstallerError = SQLInstallerErrorW
Macro SQLDriverConnect = SQLDriverConnectW
Macro SQLGetDiagRec = SQLGetDiagRecW
Macro SQLPrepare = SQLPrepareW
Macro SQLExecDirect = SQLExecDirectW
#Else
Macro SQLConfigDataSource = SQLConfigDataSourceA
Macro SQLInstallerError = SQLInstallerErrorA
Macro SQLDriverConnect = SQLDriverConnectA
Macro SQLGetDiagRec = SQLGetDiagRecA
Macro SQLPrepare = SQLPrepareA
Macro SQLExecDirect = SQLExecDirectA
#EndIf
And CSql.inc
'CSql.inc
Class CSql Common
Instance m_strConnectionString As BStr
Instance m_strDatabase As BStr
Instance m_strDriver As BStr
Instance m_strServer As BStr
Instance m_strDBQ As BStr
Instance m_szCnStrOut As ZStr * 512
Instance iBytes As Integer
Instance swStrLen As Integer
Instance m_hEnvr As Dword
Instance m_hConn As Dword
Instance m_iNativeErrPtr As Long
Instance m_iTextLenPtr As Integer
Instance m_szErrCode As ZStr * 8
Instance m_szErrMsg As ZStr * 512
Instance m_blnConnected As Long
Interface ISql : Inherit IUnknown
Property Get strDatabase() As BStr
Property=m_strDatabase
End Property
Property Set strDatabase(Byval strName As BStr)
m_strDatabase=strName
End Property
Property Get strDriver() As BStr
Property=m_strDriver
End Property
Property Set strDriver(Byval strName As BStr)
m_strDriver=strName
End Property
Property Get strServer() As BStr
Property=m_strServer
End Property
Property Set strServer(Byval strName As BStr)
m_strServer=strName
End Property
Property Get hConn() As Dword
Property=m_hConn
End Property
Property Get strDBQ() As BStr
Property=m_strDBQ
End Property
Property Set strDBQ(Byval strName As BStr)
m_strDBQ=strName
End Property
Property Get strConnectionString() As BStr
Property=m_strConnectionString
End Property
Property Set strConnectionString(Byval strName As BStr)
m_strConnectionString=strName
End Property
Property Get blnConnected() As Long
Property=m_blnConnected
End Property
Property Set blnConnected(Byval iConnected As Long)
m_blnConnected=iConnected
End Property
Property Get strErrCode() As BStr
Property=m_szErrCode
End Property
Property Get strErrMsg() As BStr
Property=m_szErrMsg
End Property
Property Get iNativeErrCode() As Long
Property=m_iNativeErrPtr
End Property
Method MakeConnectionString()
If m_strConnectionString="" Then
Select Case m_strDriver
Case "SQL Server"
If m_strDBQ="" Then
m_strConnectionString= _
"DRIVER=" & m_strDriver & ";" & _
"SERVER=" & m_strServer & ";"
Else
m_strConnectionString= _
"DRIVER=" & m_strDriver & ";" & _
"SERVER=" & m_strServer & ";" & _
"DATABASE=" & m_strDatabase & ";" & _
"DBQ=" & m_strDBQ & ";"
End If
Case "Microsoft Access Driver (*.mdb)"
m_strConnectionString= _
"DRIVER=" & m_strDriver & ";" & _
"DBQ=" & m_strDBQ & ";"
Case "Microsoft Excel Driver (*.xls)"
m_strConnectionString= _
"DRIVER=" & m_strDriver & ";" & _
"DBQ=" & m_strDBQ & ";"
End Select
End If
End Method
Method ODBCConnect()
Local szCnIn As ZStr * 512
Local szCnOut As ZStr * 512
Local iRet As Long
Me.MakeConnectionString()
Call SQLAllocHandle(%SQL_HANDLE_ENV,%SQL_NULL_HANDLE,m_hEnvr)
Call SQLSetEnvAttr(m_hEnvr,%SQL_ATTR_ODBC_VERSION,ByVal %SQL_OV_ODBC3,%SQL_IS_INTEGER)
Call SQLAllocHandle(%SQL_HANDLE_DBC,m_hEnvr,m_hConn)
szCnIn=m_strConnectionString
iRet=SQLDriverConnect(m_hConn,0,szCnIn,Len(szCnIn),szCnOut,512,iBytes,%SQL_DRIVER_NOPROMPT)
If iRet=0 Or iRet=1 Then
m_blnConnected=%TRUE
Else
m_blnConnected=%FALSE
Call SQLGetDiagRec(%SQL_HANDLE_DBC,m_hConn,1,m_szErrCode,m_iNativeErrPtr,m_szErrMsg,512,m_iTextLenPtr)
End If
End Method
Method ODBCGetDiagRec(Byval hStmt As Dword)
Call SQLGetDiagRec(%SQL_HANDLE_STMT,hStmt,1,m_szErrCode,m_iNativeErrPtr,m_szErrMsg,512,m_iTextLenPtr)
End Method
Method ODBCDisconnect()
If Me.blnConnected=%TRUE Then
Call SQLDisconnect(m_hConn) 'Disconnect From Data Source
Call SQLFreeHandle(%SQL_HANDLE_DBC,m_hConn) 'Free Connection Handle
Call SQLFreeHandle(%SQL_HANDLE_ENV,m_hEnvr) 'Free Environment Handle
End If
End Method
End Interface
End Class
So there you have a full working PowerBASIC program that does, to the best of my knowledge, everything my original Visual Basic 6 program does as first described with an ADO Data Control feeding into a Data Bound Grid Control connecting to the Titles Table of Biblio.mdb. If compiled with the PowerBASIC includes in a Release Build, i.e., %Debug not defined, it compiles to 36864 bytes. With Jose's includes it comes to 40,960 bytes. If we add the 22,016 of the grid dll we have 58,880 bytes or 58 K. Comparing that to the Visual Basic 6 project with the ADO Data Control and the Data Bound Grid we have this...
DataGrid.cab 9457 K
Setup.exe 137 K
Setup.lst 4 K
=====================
9598 K
Almost 10 Megabytes. Dividing it out the PowerBASIC critter is 165 times smaller! OK, lets get to the details.
For database access I just used my own simple ODBC wrapper class. Its primary purpose is to hide the nastiness of SQLDriverConnect(), which can get ugly. In fnWndProc_OnCreate(), which is VB's Form_Load(), you'll see the code to open the Titles Table of Biblio.mdb. I used equates there ($DB_PATH and $DB_DRIVER), but it amounts to this...
Local pSql As ISql
pSql = Class "CSql"
pSql.strDBQ = "C:\Program Files (x86)\Microsoft Visual Studio\VB98\Biblio.mdb"
pSql.strDriver = "Microsoft Access Driver (*.mdb)"
Call pSql.ODBCConnect()
If pSql.blnConnected Then
...
... do whatever...
pSql.ODBCDisconnect()
End If
[CODE]
...anytime you want to read/write database data. Within the enclosing If in fnWndProc_OnCreate() you'll see a call to blnGetRecordCount(pSql, iRecordCount) which code determines the count of records in the Titles Table, which is around 8600. Then you'll note I multiply iRecordCount by 1.01. Reason I did that was to configure the grid to hold an additional 86 rows if somebody is inclined to add more books. That's how I deal with 'AddNew' functionality. Quick and dirty I admit. Now the next several lines of code is definitely going to require some explanation from me!
[CODE]
hHeap = GetProcessHeap()
pEditFlags = HeapAlloc(hHeap, %HEAP_ZERO_MEMORY, sizeof(EditFlags))
If pEditFlags Then
@pEditFlags.iRecords = iRecordCount
@pEditFlags.pEdits = HeapAlloc(hHeap, %HEAP_ZERO_MEMORY, iRecordCount+1)
...
...
The situation is this. You've got a grid full of data in row x column format and you've got to track what the user does to the data. And how in the world would you do that? Well, look up in my CGridEvents Class. There are Grid_OnKeyPress() and Grid_OnKeyDown() Event Procedures that fire every time the user presses a key while focus is in a grid cell. And the row and column of the cell where this occurred is transferred through the parameters! So that's the key. So a flag, i.e., a Boolean true/false setup, is going to have to be created to track all this. Except there's going to be more than one scalar true/false value. The Titles Table has about 8700 rows and each row comprises 8 columns or fields. Multiplying that out comes to 68800 Boolean flags! So one way of doing it would be to create a two dimensional byte array with 8700 rows and 8 columns. The overhead of doing that would be about 68 K. Another related issue is the scope of the array. Any changes a user makes to the data, which would set one of these flags, must persist through the lifetime of the program run. This suggests global or static storage. However, I prefer to make life interesting and tackle challenges, and I don't want life to become too easy, so I never use global variables. Have you noticed there haven't been any in any of the programs I've posted so far?
So here's what I do. I don't use byte variables to track each field or column in the grid. I just use bits. The Titles Table has 8 fields or columns, so that works out good to just allocate a byte for each row, and set the bit within the byte corresponding to each column. When the Titles Table is Opened by blnGetRecordCount() and the iRecordCount parameter is initialized to the count of records in the table which actually looks to be 8569, then I do two separate memory allocations with HeapAlloc(). First, I allocate one of these in fnWndProc_OnCreate() ...
Type EditFlags
iRecords As Long
pEdits As Byte Ptr
End Type
You'll find that Type near the top of FHGrid2.bas. Since it contains two elements each of which occupies four bytes on a 32 bit operating system, the whole thing is just eighy bytes in size. So this function call...
Local pEditFlags As EditFlags Ptr
pEditFlags = HeapAlloc(hHeap, %HEAP_ZERO_MEMORY, sizeof(EditFlags))
...will return to me in pEditFlags the starting address of an 8 byte block of memory where those two variables will live for the duration of a program run. I store that address in the 2nd four byte 'slot' in the WNDCLASSEX::cbWndExtra bytes of Window Class memory for the "Test My Grid" Window Class (Registered in WinMain())....
SetWindowLong(Wea.hWnd, 4, pEditFlags)
That memory is released in fnWndProc_OnDestroy(), which is about equivalent to Form_Unload() in old VB6. But next in fnWndProc_OnCreate I do this ...
@pEditFlags.iRecords = iRecordCount
@pEditFlags.pEdits = HeapAlloc(hHeap, %HEAP_ZERO_MEMORY, iRecordCount+1)
I store the number of records or rows that will be allocated in the grid at @pEditFlags.iRecords, and that is something like that 8600 – 8700 number. Then for ...
@pEditFlags.pEdits = HeapAlloc(hHeap, %HEAP_ZERO_MEMORY, iRecordCount + 1)
...I do another HeapAlloc() call to get a pointer to another block of memory containing 8600 – 8700 or so bytes – one byte for each row of the grid. I allocate one more than I need so I can use 1 based indexing instead of zero based indexing. So I'm wasting one byte! The grid returns one based index info in those KeyPress()/KeyDown() event procedures. And related closely to all this is the KeyPress() Event proceure itself in Class CgridEvents...
Class CGridEvents As Event
Instance hMain As Dword
Class Method Create()
hMain=FindWindow("Test My Grid","Test My Grid")
End Method
Interface IGridEvents $IID_IGridEvents : Inherit IAutomation
Method Grid_OnKeyPress(Byval iKeyCode As Long, Byval iKeyData As Long, Byval iRow As Long, Byval iCol As Long, Byref blnCancel As Long)
Local pEditFlags As EditFlags Ptr
pEditFlags=GetWindowLong(hMain,4)
If pEditFlags And @pEditFlags.pEdits Then
@pEditFlags.@pEdits[iRow] = @pEditFlags.@pEdits[iRow] Or 2^(iCol-1)
End If
End Method
...
...
End Interface
End Class
Let me explain what's taking place there. In fnWndProc_OnCreate() we have this variable declaration...
Local pSink As IGridEvents
...and later on down when we set up the event sink, we have this...
pSink = Class "CGridEvents"
Events From pGrid Call pSink
Don't get put off by the terminology. In the COM documentation code which gets called from within a COM object is sometimes referred to as a 'sink', i.e., the code is 'sinking' the events fired off by the COM object as the user interacts with it.
And when the CGridEvents Class is instantiated its Create() Method, i.e., its 'Constructor' in OOP (Object Oriented Programming) speak, is called. And looking in 'Class Method Create()' above what you can see getting done is a call to the Windows Api function FindWindow(), where its looking for a window of Class "Test My Grid" which has "Test My Grid" for its caption. Its storing the Window Handle of the Window it finds in its single Instance variable hMain. That number, whatever it is, will persist for the lifetime of the app's run in that Instance variable. It will be there when the user interacts with the grid data by pressing a key to modify an existing record, or add a new one. When that happens I access our stored byte array allocated in fnWndProc_OnCreate(), and I set the zero based bit corresponding to the col parameter passed in from the grid...
Local pEditFlags As EditFlags Ptr
pEditFlags=GetWindowLong(hMain,4)
If pEditFlags And @pEditFlags.pEdits Then
@pEditFlags.@pEdits[iRow] = @pEditFlags.@pEdits[iRow] Or 2^(iCol-1)
End If
Of course, the iRow parameter will index us into the correct byte offset from the initial pEditFlags memory allocation. And we'll 'Or' that bit into place using the expression ...
@pEditFlags.@pEdits[iRow] Or 2^(iCol-1)
If the first column is edited for example, iCol will come in equaling 1. 1 – 1 equals zero, so 2 or any number for that matter raised to the zeroth power equals 1. So the zeroth zero based bit will be set to 1, informing the program that the 1st field of the iRow record has been edited. So on and so forth for all the other bits. If a new record is entered at the end of the grid data and all eight fields/columns are filled in, that byte will end up with an arithmetic value of 255, i.e.,
1 X 2 ^ 0 = 1
1 X 2 ^ 1 = 2
1 X 2 ^ 2 = 4
1 X 2 ^ 3 = 8
1 X 2 ^ 4 = 16
1 X 2 ^ 5 = 32
1 X 2 ^ 6 = 64
1 X 2 ^ 7 = 128
=====================
255
I might point out there are other ways of going about this that are in some ways simpler. For example, one might simply allocate iRecordCount + 1 Word variables, and store the iRecordCount number at offset zero something like this ...
Local pEdits As Word Ptr
PEdits = HeapAlloc(GetProcessHeap(), %HEAP_ZERO_MEMORY, (iRecordCount + 1) * Sizeof(Word))
That way you would be able to do away with the EditFlags Type. Only thing is it would use double the memory needed, and would be wasting bits 8 through 15 of every Word because we only have 8 columns. But we can't use bytes and store 8659 at @pEdit[0] if we're accessing bytes because 8659 won't store in a byte. That's why I used a UDT (User Defined Type) that contained a Long member to store big numbers, and a Byte Pointer member to just store column information where the iCol returned will never exceed 8. Verstehen Sie?
About the last thing I might mention in fnWndProc_OnCreate() is how the grid was created. As I mentioned, we can just use PowerBASIC's NewCom statement, and all the information needed to configure the grid is contained in the FHGrid9::CreateGrid() call..
pGrid = NewCom "FHGrid9.Grid"
...
...
strSetup= _
"300:Title:^:edit," & _
"200:Year Published:^:edit," & _
"150:ISBN:^:edit," & _
"90:PubID:^:edit," & _
"200:Description:^:edit," & _
"90:Notes:^:edit," & _
"100:Subject:^:edit," & _
"110:Comments:^:edit"
pGrid.CreateGrid(Wea.hWnd,strSetup,10,10,850,500,iRecordCount,8,20,0,0,"Times New Roman",12,%FW_LIGHT)
The column information is a comma delimited string, and each sub-string between the commas is further delimited into sub-strings with the ':' character. For example, column 1 is 300 pixels wide, the caption is "Title", it is centered in the column label, i.e., '^', and an edit control is used for the cell (the only other choice at this time for my grid is a combo box). You can look at the CreateGrid() method in the interface definition to see what all the parameters are. Otherwise, I've added comments to the code here and there explaining things you might be unfamiliar with.
But I want to discuss deletion a bit. The way it works in my grid is that it has built into it a concept known as selection. When you click any of the buttons along the left side of each row it highlights the whole row. In other words, it selects that row. Clicking on that button again deselects it. But while a row is selected, if you hit your [DELETE] key, a Grid_OnDelete(Byval iRow As Long) message is fired at the client's sink. But that won't cause the row to be deleted. I didn't want to make it all that automatic, for a foresaw usages in applications where deletions wouldn't be allowed or needed. So what has to happen in Grid_OnDelete() if you want to indeed delete that row is to call IGrid::DeleteRow(Byval iRow As Long), passing in the same iRow parameter as the one passed into the event procedure. But you must realize that doing that will only delete the data the grid is storing for that row – it won't delete the data in the underlying data source. For that you'll need to write additional code. If the underlying data is from a relational database supporting SQL, then you'll need to execute a DELETE FROM statement.
I've explained above how I use bits in byte variables to track user edits to data in the grids, and how I create an array of these bytes synchronized with the rows of grid data. But deletions could desynchronize the alignment of bytes with the rows they are to track. So in the deletion code quite early on I call UpdateDatabase() to take care of and clean up any updates or insertions the user might have made. After that a DELETE FROM query is executed to delete the data from the database, and one of the last calls in Grid_OnDelete() is the pGrid.DeleteRow(iRow) call which removes the data from the grid for that row.
I'll move on to the MSFlexGrid now. That defeated me with deletions, so the code I'll present works fine for updates and insertions, but in the couple hours I threw at deletions I failed. Perhaps you'll have more luck. I suppose part of the problem is that with my grid I wrote it myself and have full knowledge of how it works. Some of the behaviors of the MSFlexGrid just mystify me even though I've used it a fair amount in both Visual Basic and PowerBASIC. For one thing, those little buttons to the left of each row aren't enabled like in my grid. At least, they don't respond in any way to clicks. And when I try to select a row, the 1st cell to the right of the button doesn't select. I've no idea why not. Another thing about the MSFlxGrd is that the event procedures mostly have few or no parameters. Here is the KeyPress() event proc from my grid ...
Method Grid_OnKeyPress(Byval iKeyCode As Long, Byval iKeyData As Long, Byval iRow As Long, Byval iCol As Long, Byref blnCancel As Long)
And here it is from the MSFlxGrd...
Method KeyPress <-603> (Byref KeyAscii As Integer)
So when a KeyPress() comes in, you've got to call dispinterface methods on the IGrid interface to retrieve the row and column where the keypress occurred. And even more miserably, when the user sets focus to a cell and attempts to type something in, the default behavior of the grid is to do nothing. At least as far as I know. Unless there is some setting to cause the text to show up. What I've always done going all the way back to my VB days in the late 90s was to execute code like so for each keypress ...
Method KeyPress <-603> (Byref KeyAscii As Integer)
Local pGridInterfaces As GridInterfaces Ptr
Local pEditFlags As EditFlags Ptr
Local pFlexGrid As IMSFlexGrid
Local pDisp As IDispatch
Local strText As WString
Local iRow,iCol As Long
pGridInterfaces=GetWindowLong(hMain,0)
If pGridInterfaces Then
If @pGridInterfaces.pGrid Then
CObj(pFlexGrid,@pGridInterfaces.pGrid)
pFlexGrid.AddRef()
pDisp=pFlexGrid
If IsObject(pDisp) Then
Object Get pDisp.Row To iRow
Object Get pDisp.Col To iCol
pEditFlags=GetWindowLong(hMain,4)
If pEditFlags And @pEditFlags.pEdits Then
@pEditFlags.@pEdits[iRow] = @pEditFlags.@pEdits[iRow] Or 2^(iCol-1)
End If
If KeyAscii=8 Then
Object Get pDisp.Text() To strText
strText=Left$(strText,Len(strText)-1)
Object Let pDisp.Text()=strText
Else
Object Get pDisp.Text() To strText
strText=strText+Chr$(KeyAscii)
Object Let pDisp.Text()=strText
End If
End If
End If
End If
End Method
But without further adieu here is MSFlexGrid_JRI.bas. The 'JRI' part stands for Jose Roca Includes. It uses his OleCon.inc ActiveX Control Container as opposed to the ATL code. And it uses the COM includes generated by his TypeLib Browser ...
'Program = MSFlexGrid_JRI
#Compile Exe "MSFlexGrid_JRI"
#Register None
#Dim All
'%DEBUG = 1
%UNICODE = 1
#If %Def(%UNICODE)
Macro ZStr = WStringz
Macro BStr = WString
%SIZEOF_CHAR = 2
#Else
Macro ZStr = Asciiz
Macro BStr = String
%SIZEOF_CHAR = 1
#EndIf
Type WndEventArgs
wParam As Long
lParam As Long
hWnd As Dword
hInst As Dword
End Type
Type GridInterfaces
pGrid As Dword Ptr
pSink As Dword Ptr
End Type
Type EditFlags
iRecords As Long
pEdits As Byte Ptr
End Type
'$DB_PATH = "C:\Program Files (x86)\Microsoft Visual Studio\VB98\db1.mdb"
$DB_PATH = "C:\Program Files\Microsoft Visual Studio\VB98\db1.mdb"
$DB_DRIVER = "Microsoft Access Driver (*.mdb)"
#Include "Windows.inc" ' use Jose Roca's includes
#Include "OleCon.inc"
#Include "SqlIncs.inc"
#Include "CSql.inc"
#Include "MSFlexGridLib.inc"
#Include "MSFlexGridLibEvents.inc"
%ID_CONTAINER = 2000
Macro CObj(pUnk, dwAddr) = Poke Dword, Varptr(pUnk), dwAddr
#If %Def(%Debug)
Sub Prnt(strLn As BStr)
Local iLen, iWritten As Long
Local hStdOutput As Dword
Local strNew As BStr
hStdOutput=GetStdHandle(%STD_OUTPUT_HANDLE)
strNew=strLn + $CrLf
iLen = Len(strNew)
WriteConsole(hStdOutput, Byval Strptr(strNew), iLen, iWritten, Byval 0)
End Sub
#EndIf
Sub GridSetup(Byref pGrid As IMSFlexGrid, Byval iRecCt As Long)
pGrid.SelectionMode = 0
pGrid.AllowUserResizing = %AllowUserResizeSettings.flexResizeColumns
pGrid.FontName = "Times New Roman"
pGrid.FontSize = 10
pGrid.Cols = 9
pGrid.Rows = iRecCt
pGrid.ColWidth(0) = 200
pGrid.ColWidth(1) = 7000
pGrid.ColWidth(2) = 1350
pGrid.ColWidth(3) = 1600
pGrid.ColWidth(4) = 700
pGrid.ColWidth(5) = 3000
pGrid.ColWidth(6) = 3000
pGrid.ColWidth(7) = 2000
pGrid.ColWidth(8) = 4000
pGrid.Col = 1
pGrid.Row = 0
pGrid.Text = "Title"
pGrid.Col = 2
pGrid.Text = "Year Published"
pGrid.Col = 3
pGrid.Text = "ISBN"
pGrid.Col = 4
pGrid.Text = "PubID"
pGrid.Col = 5
pGrid.Text = "Description"
pGrid.Col = 6
pGrid.Text = "Notes"
pGrid.Col = 7
pGrid.Text = "Subject"
pGrid.Col = 8
pGrid.Text = "Comments"
End Sub
Function blnGetRecordCount(Byref pSql As ISql, Byref iRecCt As Long) As Long
Local szQuery As ZStr*64
Local hStmt As Dword
Local iJnk As Long
szQuery="SELECT Count(*) As RecordCount FROM Titles"
Call SQLAllocHandle(%SQL_HANDLE_STMT,pSql.hConn(),hStmt)
Call SQLBindCol(hStmt,1,%SQL_C_ULONG,iRecCt,0,iJnk)
Call SQLExecDirect(hStmt,szQuery,%SQL_NTS)
Call SQLFetch(hStmt)
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
If iRecCt Then
Function=%True
Else
Function=%False
End If
End Function
Function blnLoadTitles(Byref pSql As ISql, Byref pGrid As IMSFlexGrid) As Long
Local szQuery As ZStr * 256
Local szTitle As ZStr * 256
Local szISBN As ZStr * 24
Local iYrPub As Integer
Local iPubID As Long
Local szDescription As ZStr * 128
Local szNotes As ZStr * 128
Local szSubject As ZStr * 128
Local szComments As ZStr * 256
Local iVar As Long
Local hStmt As Dword
Local iLen() As Long
Register i As Long
#If %Def(%Debug)
Prnt " Entering blnLoadTitles()"
#Endif
szQuery = "SELECT Title, [Year Published], ISBN, PubID, Description, Notes, Subject, Comments FROM Titles ORDER BY ISBN;
Redim iLen(8) As Long
Call SQLAllocHandle(%SQL_HANDLE_STMT,pSql.hConn(),hStmt)
Call SQLBindCol(hStmt,1,%SQL_C_WCHAR,szTitle,510,iLen(1))
Call SQLBindCol(hStmt,2,%SQL_C_SHORT,iYrPub,0,iLen(2))
Call SQLBindCol(hStmt,3,%SQL_C_WCHAR,szISBN,46,iLen(3))
Call SQLBindCol(hStmt,4,%SQL_C_LONG,iPubID,0,iLen(4))
Call SQLBindCol(hStmt,5,%SQL_C_WCHAR,szDescription,110,iLen(5))
Call SQLBindCol(hStmt,6,%SQL_C_WCHAR,szNotes,110,iLen(6))
Call SQLBindCol(hStmt,7,%SQL_C_WCHAR,szSubject,110,iLen(7))
Call SQLBindCol(hStmt,8,%SQL_C_WCHAR,szComments,510,iLen(8))
iVar=SQLExecDirect(hStmt,szQuery,%SQL_NTS)
If iVar=%SQL_SUCCESS Or iVar=%SQL_SUCCESS_WITH_INFO Then
i=1
pGrid.ColAlignment(1)=1
Do While SQLFetch(hStmt)<>%SQL_NO_DATA
pGrid.Row=i
pGrid.Col=1 : If iLen(1) Then pGrid.Text=szTitle
pGrid.Col=2 : If iLen(2) Then pGrid.Text=Str$(iYrPub)
pGrid.Col=3 : If iLen(3) Then pGrid.Text=szISBN
pGrid.Col=4 : If iLen(4) Then pGrid.Text=Str$(iPubID)
pGrid.Col=5 : If iLen(5) Then pGrid.Text=szDescription
pGrid.Col=6 : If iLen(6) Then pGrid.Text=szNotes
pGrid.Col=7 : If iLen(7) Then pGrid.Text=szSubject
pGrid.Col=8 : If iLen(8) Then pGrid.Text=szComments
Incr i
Loop
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Else
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Function=%False : Exit Function
End If
pGrid.Refresh()
Erase iLen()
#If %Def(%Debug)
Prnt " " & szQuery
Prnt " Leaving blnLoadTitles()"
#Endif
Function=%True
End Function
Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
Local pGridInterfaces As GridInterfaces Ptr
Local lpCreateStruct As CREATESTRUCT Ptr
Local pEvents As DMSFlexGridEventsImpl
Local pEditFlags As EditFlags Ptr
Local hContainer,hHeap As Dword
Local pFlexGrid As IMSFlexGrid
Local iRecordCount As Long
Local hr,hCtl As Long
Local pSql As ISql
#If %Def(%Debug)
Call AllocConsole()
Prnt "Entering fnWndProc_OnCreate()"
#EndIf
lpCreateStruct=Wea.lParam : Wea.hInst=@lpCreateStruct.hInstance
Call OC_WinInit()
hHeap=GetProcessHeap()
pGridInterfaces=HeapAlloc(hHeap,%HEAP_ZERO_MEMORY,sizeof(GridInterfaces))
If pGridInterfaces=0 Then
MsgBox("Memory Allocation Failure")
Function=-1 : Exit Function
End If
Call SetWindowLong(Wea.hWnd,0,pGridInterfaces)
hContainer=CreateWindowEx _
( _
0, _
$OC_ClassNAME, _
"MSFlexGridLib.MSFlexGrid;RTLKEY:72E67120-5959-11cf-91F6-C2863C385E30", _
%WS_CHILD OR %WS_VISIBLE, _
10, _
10, _
850, _
500, _
Wea.hWnd, _
%ID_CONTAINER, _
Wea.hInst, _
Byval %NULL _
)
If hContainer=0 Then
#If %Def(%Debug)
Prnt " hContainer=0"
#EndIf
Function=-1 : Exit Function
End If
pFlexGrid=OC_GetDispatch(hContainer)
If IsObject(pFlexGrid) Then
#If %Def(%Debug)
Prnt " pFlexGrid Is Something!"
#EndIf
pFlexGrid.AddRef()
@pGridInterfaces.pGrid=Objptr(pFlexGrid)
pEvents = Class "CDMSFlexGridEvents"
If IsObject(pEvents) Then
@pGridInterfaces.pSink=Objptr(pEvents)
Events From pFlexGrid Call pEvents
pSql=Class "CSql"
pSql.strDBQ=$DB_PATH
pSql.strDriver=$DB_DRIVER
Call pSql.ODBCConnect()
If pSql.blnConnected Then
If blnGetRecordCount(pSql, iRecordCount) Then
#If %Def(%Debug)
Prnt " pFlexGrid = " & Str$(Objptr(pFlexGrid))
Prnt " iRecordCount = " & Str$(iRecordCount)
#EndIf
iRecordCount=iRecordCount*1.01
pEditFlags=HeapAlloc(hHeap,%HEAP_ZERO_MEMORY,sizeof(EditFlags))
#If %Def(%Debug)
Prnt " iRecordCount = " & Str$(iRecordCount)
Prnt " pEditFlags = " & Str$(pEditFlags)
#EndIf
If pEditFlags Then
SetWindowLong(Wea.hWnd,4,pEditFlags)
@pEditFlags.iRecords=iRecordCount
@pEditFlags.pEdits=HeapAlloc(hHeap,%HEAP_ZERO_MEMORY,iRecordCount+1)
#If %Def(%Debug)
Prnt " @pEditFlags.iRecords = " & Str$(@pEditFlags.iRecords)
Prnt " @pEditFlags.pEdits = " & Str$(@pEditFlags.pEdits)
#EndIf
If @pEditFlags.pEdits Then
Call GridSetup(pFlexGrid,iRecordCount)
Call blnLoadTitles(pSql, pFlexGrid)
End If
End If
End If
pSql.ODBCDisconnect()
End If
#If %Def(%Debug)
Prnt " pGridInterfaces = " & Str$(pGridInterfaces)
Prnt " Objptr(pEvents) = " & Str$(Objptr(pEvents))
#EndIf
End If
End If
#If %Def(%Debug)
Prnt "Leaving fnWndProc_OnCreate()" & $CrLf
#EndIf
fnWndProc_OnCreate=0
End Function
Function blnUpdateRecord(Byval iRecord As Long, Byval pRecord As Byte Ptr, Byref Sql As ISql, Byref pGrid As IMSFlexGrid) As Long
Local strQuery, strField, strPrimaryKey As BStr
Local iReturn As Long
Local hStmt As Dword
Register i As Long
#If %Def(%Debug)
Prnt " Entering blnUpdateRecord()"
Prnt " Record #" & Str$(iRecord) & " Was Edited"
Prnt " @pRecord = " & Str$(@pRecord)
#EndIf
pGrid.Row=iRecord
strQuery="UPDATE Titles SET "
For i=0 To 7
If IsTrue(@pRecord And 2^i) Then
Select Case As Long i
Case 0
pGrid.Col=1
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Title=" & Chr$(39) & strField & Chr$(39) & ","
Case 1
pGrid.Col=2
strField=pGrid.Text()
strQuery = strQuery & "[Year Published]=" & strField & ","
Case 3
pGrid.Col=4
strField=pGrid.Text()
strQuery = strQuery & "PubID=" & strField & ","
Case 4
pGrid.Col=5
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Description=" & Chr$(39) & strField & Chr$(39) & ","
Case 5
pGrid.Col=6
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Notes=" & Chr$(39) & strField & Chr$(39) & ","
Case 6
pGrid.Col=7
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Subject=" & Chr$(39) & strField & Chr$(39) & ","
Case 7
pGrid.Col=8
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & "Comments=" & Chr$(39) & strField & Chr$(39) & ","
End Select
End If
Next i
strQuery=Left$(strQuery,Len(strQuery)-1)
pGrid.Col=3
strPrimaryKey=" WHERE ISBN=" & Chr$(39) & pGrid.Text() & Chr$(39) & ";"
strQuery=strQuery+strPrimaryKey
#If %Def(%Debug)
Prnt " strQuery = " & strQuery
#EndIf
Call SQLAllocHandle(%SQL_HANDLE_STMT,Sql.hConn(),hStmt)
iReturn=SQLExecDirect(hStmt,Byval Strptr(strQuery),%SQL_NTS)
If iReturn<>%SQL_SUCCESS And iReturn<>%SQL_SUCCESS_WITH_INFO Then
Sql.ODBCGetDiagRec(hStmt)
#If %Def(%Debug)
Prnt " iReturn = " & Str$(iReturn)
Prnt " %SQL_SUCCESS = " & Str$(%SQL_SUCCESS)
Prnt " %SQL_SUCCESS_WITH_INFO = " & Str$(%SQL_SUCCESS_WITH_INFO)
Prnt " Sql.iNativeErrCode = " & Str$(Sql.iNativeErrCode)
Prnt " Sql.strErrMsg = " & Sql.strErrMsg
Prnt " Sql.strErrCode = " & Sql.strErrCode
Prnt " Leaving blnUpdateRecord()"
#EndIf
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Function=%False : Exit Function
End If
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
#If %Def(%Debug)
Prnt " Leaving blnUpdateRecord()"
#EndIf
Function=%True
End Function
Function blnInsertRecord(Byval iRecord As Long, Byval pRecord As Byte Ptr, Byref Sql As ISql, Byref pGrid As IMSFlexGrid) As Long
Local strQuery, strField As BStr
Local iReturn As Long
Local hStmt As Dword
Register i As Long
#If %Def(%Debug)
Prnt " Entering blnInsertRecord()"
Prnt " Record #" & Str$(iRecord) & " Was Edited"
Prnt " @pRecord = " & Str$(@pRecord)
Prnt $CrLf
#EndIf
pGrid.Row=iRecord
strQuery="INSERT INTO Titles ("
For i=0 To 7
If IsTrue(@pRecord And 2^i) Then
Select Case As Long i
Case 0
strQuery=strQuery+"Title,"
Case 1
strQuery=strQuery+"[Year Published],"
Case 2
strQuery=strQuery+"ISBN,"
Case 3
strQuery=strQuery+"PubID,"
Case 4
strQuery=strQuery+"Description,"
Case 5
strQuery=strQuery+"Notes,"
Case 6
strQuery=strQuery+"Subject,"
Case 7
strQuery=strQuery+"Comments,"
End Select
End If
Next i
strQuery=Left$(strQuery,Len(strQuery)-1)+") VALUES ("
For i=0 To 7
If IsTrue(@pRecord And 2^i) Then
Select Case As Long i
Case 0 ' Title
pGrid.Col=1
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 1 ' [Year Published]
pGrid.Col=2
strField=pGrid.Text()
strQuery = strQuery & strField & ","
Case 2 ' ISBN
pGrid.Col=3
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 3 ' PubID
pGrid.Col=4
strField=pGrid.Text()
strQuery = strQuery & strField & ","
Case 4 ' Description
pGrid.Col=5
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 5 ' Notes
pGrid.Col=6
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 6 ' Subject
pGrid.Col=7
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
Case 7 ' Comments
pGrid.Col=8
strField=pGrid.Text()
If InStr(1,strField,Chr$(39)) Then
Replace Chr$(39) With "''" In strField
End If
strQuery = strQuery & Chr$(39) & strField & Chr$(39) & ","
End Select
End If
Next i
strQuery=Left$(strQuery,Len(strQuery)-1) & ");"
#If %Def(%Debug)
Prnt " strQuery = " & strQuery
#EndIf
Call SQLAllocHandle(%SQL_HANDLE_STMT,Sql.hConn(),hStmt)
iReturn=SQLExecDirect(hStmt,Byval Strptr(strQuery),%SQL_NTS)
If iReturn<>%SQL_SUCCESS And iReturn<>%SQL_SUCCESS_WITH_INFO Then
Sql.ODBCGetDiagRec(hStmt)
#If %Def(%Debug)
Prnt " iReturn = " & Str$(iReturn)
Prnt " %SQL_SUCCESS = " & Str$(%SQL_SUCCESS)
Prnt " %SQL_SUCCESS_WITH_INFO = " & Str$(%SQL_SUCCESS_WITH_INFO)
Prnt " Sql.iNativeErrCode = " & Str$(Sql.iNativeErrCode)
Prnt " Sql.strErrMsg = " & Sql.strErrMsg
Prnt " Sql.strErrCode = " & Sql.strErrCode
#Else
iReturn=MsgBox(Sql.strErrMsg, %MB_ICONERROR, "I Don't Want To Sugar Coat It ...")
#EndIf
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
Function=%False : Exit Function
End If
Call SQLFreeHandle(%SQL_HANDLE_STMT,hStmt)
#If %Def(%Debug)
Prnt " Leaving blnInsertRecord()"
Prnt $CrLf
#EndIf
Function=%True
End Function
Sub UpdateDatabase(Byval iRecords As Long, Byval pEdits As Byte Ptr, Byref pGrid As IMSFlexGrid)
Local blnDataEdited, iReturn As Long
Register i As Long
Local Sql As ISql
#If %Def(%Debug)
Prnt " Entering UpdateDatabase()"
Prnt " iRecords = " & Str$(iRecords)
Prnt " pEdits = " & Str$(pEdits)
#EndIf
For i = 1 To iRecords
If @pEdits[i] Then
blnDataEdited=%True
Exit For
End If
Next i
If blnDataEdited Then
Sql=Class "CSql"
Sql.strDBQ=$DB_PATH
Sql.strDriver=$DB_DRIVER
Call Sql.ODBCConnect()
If Sql.blnConnected Then
#If %Def(%Debug)
Prnt " Sql.blnConnected = True!"
#Endif
For i=1 To iRecords
If @pEdits[i] Then
If IsFalse(blnUpdateRecord(i,Varptr(@pEdits[i]),Sql,pGrid)) Then
If IsFalse(blnInsertRecord(i,Varptr(@pEdits[i]),Sql,pGrid)) Then
iReturn=MsgBox _
( _
"Failed To Update/Insert Record #" & Str$(i) & "!", _
%MB_ICONERROR, _
"I Don't Want To Sugar Coat It!" _
)
End If
End If
@pEdits[i]=0
End If
Next i
Sql.ODBCDisconnect()
End If
End If
#If %Def(%Debug)
Prnt " Leaving UpdateDatabase()"
#EndIf
End Sub
Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
Local pGridInterfaces As GridInterfaces Ptr
Local pEvents As DMSFlexGridEventsImpl
Local pEditFlags As EditFlags Ptr
Local pGrid As IMSFlexGrid
Local hHeap As Dword
Local bFree As Long
#If %Def(%Debug)
Prnt $CrLf & "Entering fnWndProc_OnDestroy()"
#EndIf
pGridInterfaces=GetWindowLong(Wea.hWnd,0)
#If %Def(%Debug)
Prnt " pGridInterfaces = " & Str$(pGridInterfaces)
#EndIf
If pGridInterfaces Then
If @pGridInterfaces.pSink Then
CObj(pEvents,@pGridInterfaces.pSink)
Events End pEvents
Set pEvents=Nothing
End If
If @pGridInterfaces.pGrid Then
CObj(pGrid,@pGridInterfaces.pGrid)
hHeap=GetProcessHeap()
pEditFlags=GetWindowLong(Wea.hWnd,4)
If pEditFlags Then
#If %Def(%Debug)
Prnt " pFlexGrid = " & Str$(Objptr(pGrid))
Prnt " pEditFlags = " & Str$(pEditFlags)
Prnt " @pEditFlags.iRecords = " & Str$(@pEditFlags.iRecords)
#EndIf
If @pEditFlags.pEdits Then
#If %Def(%Debug)
Prnt " @pEditFlags.pEdits = " & Str$(@pEditFlags.pEdits)
#EndIf
Call UpdateDatabase(@pEditFlags.iRecords, @pEditFlags.pEdits, pGrid)
bFree=HeapFree(hHeap,0,@pEditFlags.pEdits)
#If %Def(%Debug)
Prnt " bFree = " & Str$(bFree)
#EndIf
End If
bFree=HeapFree(hHeap,0,pEditFlags)
#If %Def(%Debug)
Prnt " bFree = " & Str$(bFree)
#EndIf
End If
Set pGrid=Nothing
End If
bFree=HeapFree(hHeap,0,pGridInterfaces)
End If
Call PostQuitMessage(0)
#If %Def(%Debug)
Prnt "Leaving fnWndProc_OnDestroy()"
#EndIf
fnWndProc_OnDestroy=0
End Function
Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
Local Wea As WndEventArgs
Select Case As Long wMsg
Case %WM_CREATE
Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
fnWndProc=fnWndProc_OnCreate(Wea)
Exit Function
Case %WM_DESTROY
Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
fnWndProc=fnWndProc_OnDestroy(Wea)
Exit Function
End Select
fnWndProc=DefWindowProc(hWnd, wMsg, wParam, lParam)
End Function
Function WinMain(ByVal hInstance As Long, ByVal hPrevInst As Long, ByVal lpCmdLn As ZStr Ptr, ByVal iShow As Long) As Long
Local szAppName As ZStr*16
Local wc As WNDCLASSEX
Local Msg As tagMsg
Local hWnd As Dword
szAppName="OCX Test" : wc.cbSize=SizeOf(wc)
wc.lpfnWndProc=CodePtr(fnWndProc) : wc.cbWndExtra=8
wc.hInstance=hInstance : wc.hIcon=LoadIcon(%NULL,ByVal %IDI_APPLICATION)
wc.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW) : wc.hbrBackground=%COLOR_BTNFACE+1
wc.lpszClassName=VarPtr(szAppName)
Call RegisterClassEx(wc)
hWnd=CreateWindowEx(0,szAppName,"Try MSFlexGrid",%WS_OVERLAPPEDWINDOW Xor %WS_MAXIMIZEBOX,200,100,880,560,0,0,hInstance,ByVal 0)
Call ShowWindow(hWnd,iShow)
While GetMessage(Msg,%NULL,0,0)
Call TranslateMessage(Msg)
Call DispatchMessage(Msg)
Wend
#If %Def(%Debug)
MsgBox("Come And Get It Before I Throw It Out!")
#EndIf
Function=msg.wParam
End Function
I'll not post CSql.inc or SqlIncs.inc because they are the same ones I previously posted above for the example with my grid, i.e., FHGrid9.dll. And I've certainly and emphatically learned my lesson of not trying to post anymore of Jose's verbose TypeLib Browser generated files. In terms of MSFlexGridLib.inc and MSFlexGridLibEvents.inc, I'll just post the changes, and you the reader will have to attempt to incorporate them into compilable code. Here are the changes to MSFlexGridLibEvents.inc ...
[CODE]
' ########################################################################################
' Class CDMSFlexGridEvents
' Interface name = DMSFlexGridEvents
' IID = {609602E0-531B-11CF-91F6-C2863C385E30}
' Event interface for Microsoft FlexGrid Control
' Attributes = 4112 [&H1010] [Hidden] [Dispatchable]
' Code generated by the TypeLib Browser 5.0.1 (c) 2011 by José Roca
' Date: 05 Sep 2014 Time: 09:17:50
' ########################################################################################
CLASS CDMSFlexGridEvents GUID$("{16980577-F116-4460-85AD-71B208AD9996}") AS EVENT
Instance hMain As Dword
Class Method Create()
#If %Def(%Debug)
Prnt " Entering Class Method Create() Of Class_DMSFlexGridEvents()"
#EndIf
hMain=FindWindow("OCX Test","Try MSFlexGrid")
#If %Def(%Debug)
Prnt " hMain = " & Str$(hMain)
Prnt " Leaving Class Method Create() Of Class_DMSFlexGridEvents()"
#EndIf
End Method
INTERFACE DMSFlexGridEventsImpl GUID$("{609602E0-531B-11CF-91F6-C2863C385E30}") AS EVENT : INHERIT IDispatch
' =====================================================================================
Method KeyPress <-603> (Byref KeyAscii As Integer)
Local pGridInterfaces As GridInterfaces Ptr
Local pEditFlags As EditFlags Ptr
Local pFlexGrid As IMSFlexGrid
Local pDisp As IDispatch
Local strText As WString
Local iRow,iCol As Long
pGridInterfaces=GetWindowLong(hMain,0)
If pGridInterfaces Then
If @pGridInterfaces.pGrid Then
CObj(pFlexGrid,@pGridInterfaces.pGrid)
pFlexGrid.AddRef()
pDisp=pFlexGrid
If IsObject(pDisp) Then
Object Get pDisp.Row To iRow
Object Get pDisp.Col To iCol
pEditFlags=GetWindowLong(hMain,4)
If pEditFlags And @pEditFlags.pEdits Then
@pEditFlags.@pEdits[iRow] = @pEditFlags.@pEdits[iRow] Or 2^(iCol-1)
End If
If KeyAscii=8 Then
Object Get pDisp.Text() To strText
strText=Left$(strText,Len(strText)-1)
Object Let pDisp.Text()=strText
Else
Object Get pDisp.Text() To strText
strText=strText+Chr$(KeyAscii)
Object Let pDisp.Text()=strText
End If
End If
End If
End If
End Method
' =====================================================================================
So the only thing needing to be insert is the Method Create() and KeyPress() event procedures.