IT-Consultant: Frederick J. Harris > Time For 64 Bit COM!
Finished C++ Conversion Of PowerBASIC Grid Code. I'm Happy!
Frederick J. Harris:
Isn't it a wonderful feeling to have tackled a complex and important coding project and to have finally finished it with a good outcome? That's how I feel now with having translated my COM based PowerBASIC Grid Control over to C++. So I know how you felt Patrice when you finally got your dlls/products working in C++! While I used Microsoft's VC 9 from Visual Studio 2008 to compile the grid for both x86 and x64, I wrote a client for testing purposes which comes in six different flavors (different languages and compilers). Before I get to the grid I'd like to talk about that testing client a little, as that’s what I’ve been working on for the past couple days since having completed the grid work last week. So this will be like a movie that starts at the end, which has been a popular theatrical technique for some time now.
First, of course, I used the same compiler, i.e., Microsoft's, for two of the clients, that is, an x86 and a x64 version. Then I used my favorite C++ compiler, which is the one I got with my Code::Blocks 10.05 installation - GCC 4.4.1-2 circa 2009 or so. That only makes 32 bit binaries though. The next two would be the latest MinGW GCC compiler, release date October 2013, which does both x86 and x64 exes….
http://tdm-gcc.tdragon.net/download
Finally, I cobbled together a PowerBASIC client using version 10, i.e., PBWin 10. Of course, that would be just for the 32 bit version of the grid. I've got to say it was pretty cool running all six of those clients - some 32 bit and some 64 bit - at the same time on my laptop! Especially when you consider that they all have the exact same GUIDS, ProgIDs, the works! And except for the PowerBASIC code they all stem from the exact same source code, line for line. The client program screen footprint is fairly small so they all fit on my screen at the same time. There is just a grid with 8 rows of dummy data and seven buttons that exercise various functionality of the grid when clicked, such as retrieving data, filling the grid, coloring rows, selecting rows, showing the Combo Box in Column 5, etc. All the clients were compiled with settings to minimize code size and strip debugging symbols from the executable. Here's the results. Read 'em and weep any of you PowerBASIC or Bob Zale haters out there!
--- Code: --- ActiveX Grid Clients
Compiler Architecture Date Size Easy String Handling
=======================================================================================
PowerBASIC Windows 10.03 x86 3/1/2011 25K Yes Native PowerBASIC
tdm-mingw-1.908.0-4.4.1-2 GCC x86 10/4/2009 27K No C Style Strings
tdm-mingw-1.908.0-4.4.1-2 GCC x86 10/4/2009 35K Yes My String Class
Microsoft VC++ 9 VStudio 2008 x64 11/8/2007 80K Yes My String Class
tdm64-gcc-4.8.1-3 GCC x86 10/6/2013 159K Yes My String Class
tdm64-gcc-4.8.1-3 GCC x64 10/6/2013 224K Yes My String Class
--- End code ---
So PowerBASIC wins at 25K. Note above I couldn't even beat my PowerBASIC client using C Style strings. That would be the 2nd example above that came in 27K using the older GCC compiler. That surprised me. Usually if I resort to C style strings and leave out any uses of 'class' or 'new' in a C++ program, I can beat out PowerBASIC's size by a hair. For some reason it didn't work here. PowerBASIC comes out smaller by a couple K.
Note the massive bloated executables from the most recent GCC offering - 224K is the smallest I could bring down the client on the x64 version. And this is for exactly the same program and functionality as the 25K PowerBASIC 10 version. What the deal is there are the new C++ 11 coding standards, which apparently forces incorporation of the winpthreads library into every binary created by the package. In fact, the installation of that package started with this unusual and noteworthy warning which had been lacking in their previous installations ...
--- Quote ---Hi! Sorry for the interruption, but you may want to take at least a few seconds
to look into some recent license changes for the software you're about to
install.
Parts of the "winpthreads" library will be compiled into every binary file (EXE
or DLL) you create. It's a necessary evil that is currently required in order to
provide support for threads and concurrency in programs compiled by GCC.
The license for winpthreads requires you to reproduce its text in every copy or
substantial portion of the winpthreads library that you distribute. This means
that even if you just want to distribute a single small executable, created with
TDM-GCC (or any winpthreads-based GCC release), you must include a copy of that
license.
Check the license out in the file "COPYING.winpthreads.txt", which will be
installed along with TDM-GCC. Consult with a lawyer if you have any concerns
about how you can use this software.
Does this new license hurt your usage of GCC? Let the developers know!
File a feature request asking them to change the winpthreads license or get rid
of GCC's winpthreads requirement, at:
https://sourceforge.net/p/mingw-w64/feature-requests/new/
Send an email to the MinGW-w64 mailing list, at:
mingw-w64-public@lists.sourceforge.net
--- End quote ---
So there you have it. Bob Zale is gone and the "Brave New World" we are entering is a world of bloat ware! Bloat ware rules! For all the good it will do I'm going to complain loudly at the above Source Forge email address. I’ve heard the saying that 'Progress Rides In A Hearse', so when some of us old folks who bemoan such things are all gone there won't even be any memory of small and efficient programs.
Anyway, now to the grid. My biggest concern (other than whether or not I'd successfully manage the translation and the thing would work) was how many K in size it would end up being. I was proud of the fact that my PowerBASIC grid was about 50K and the UPX executable packer ...
http://upx.sourceforge.net/
... could compress it to a miniscule 22K! I knew I'd have to use MSVC for the compiler because I wanted 64 bit, and in my opinion VC9 seemed to create pretty big binaries. It turned out pretty good though. I'm happy! At first I was coming in about 100K in the release build. I'm using my String Class rather than the one in the C++ Standard Library, so that helped quite a bit - probably to the tune of 30 or 40 K. Then just here at the end it occurred to me that my grid code makes very little use of my String Class code (although I do need it badly for its ParseCount / Parse functionality), so the idea occurred to me that I could include a special build of the String Class which would only contain the parsing code my grid really needed and nothing else! I was actually able to remove most of the code, and that brought the release build down to 86K. So I saved about 14 K there. Finally, the good folks at UPX just released a new version of their exe packer that does x64 binaries (my old version didn't work on x64s - I tried). So its coming in at 43 K packed. I don't think that's too bad for a reasonably featured x64 ActiveX Grid Control with built in self-registration.
All the PowerBASIC code for my translated grid came in around 3400 lines of code and except for the *.idl file its all in one file which is posted and downloadable from here ...
http://www.jose.it-berater.org/smfforum/index.php?topic=4642.0
I have the C++ version code organized pretty much according to C++ coding standards, such as they are, and here's what the file/project setup which I'm about to post looks like, with lines of code to the right ...
--- Code: ---FHGrid.dll -- ActiveX Grid Control
==================================
FHGrid.idl 58
FHGrid.def 7
Strings.h 81
Strings.cpp 806
Server.cpp 241
Registry.h 5
Registry.cpp 170
Interfaces.h 36
Grid.h 117
Grid.cpp 1121
WinCode.h 59
WinCode.cpp 1311
===================================
4012
--- End code ---
By the way, the way I worked it with my special build of the string class, is I created this #define in it ...
#define JUST_NEED_PARSE
... and if that's not commented out, then everything I don't need is left out using #ifndef conditional compilation logic. You'll see that if you look at the string class code. You'll see that in the Strings.cpp file.
I'll start posting the code now, and discuss it afterwards ...
Frederick J. Harris:
We'll start small. Here is FHGrid.def ...
--- Code: ---;//FHGrid.def
LIBRARY "FHGrid"
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
--- End code ---
And even slaller, FHGrid.rc
--- Code: ---1 TYPELIB "FHGrid.tlb"
--- End code ---
Now, FHGrid.idl
--- Code: ---// FHGrid.idl
import "unknwn.idl";
[object, uuid(30000000-0000-0000-0000-000000000001), oleautomation] interface IGrid : IUnknown
{
HRESULT CreateGrid
(
[in] HWND hParent,
[in] BSTR strSetup,
[in] int x,
[in] int y,
[in] int cx,
[in] int cy,
[in] int iRows,
[in] int iCols,
[in] int iRowHt,
[in] COLORREF iSelectionBackColor,
[in] COLORREF iSelectionTextColor,
[in] BSTR strFontName,
[in] int iFontSize,
[in] int iFontWeight
);
HRESULT SetRowCount([in] int iRowCount, [in] int blnForce);
HRESULT GetRowCount([out, retval] int* iRowCount);
HRESULT SetData([in] int iRow, [in] int iCol, [in] BSTR strData);
HRESULT GetData([in] int iRow, [in] int iCol, [out, retval] BSTR* strData);
HRESULT FlushData();
HRESULT Refresh();
HRESULT GetVisibleRows([out, retval] int* iVisibleRows);
HRESULT GethGrid([out, retval] HWND* hWnd);
HRESULT GethCell([in] int iRow, [in] int iCol, [out, retval] HWND* hCell);
HRESULT GethComboBox([in] int iCol, [out, retval] HWND* hCombo);
HRESULT SetCellAttributes([in] int iRow, [in] int iCol, [in] int iBackColor, [in] int iTextColor);
HRESULT DeleteRow([in] int iRow);
};
[object, uuid(30000000-0000-0000-0000-000000000002), oleautomation] interface IGridEvents : IUnknown
{
HRESULT Grid_OnKeyPress([in] int iKeyCode, [in] int iKeyData, [in] int iRow, [in] int iCol, [out] int* blnCancel);
HRESULT Grid_OnKeyDown([in] int KeyCode, [in] int iKeyData, [in] int iCellRow, [in] int iGridRow, [in] int iCol, [out] int* blnCancel);
HRESULT Grid_OnLButtonDown([in] int iCellRow, [in] int iGridRow, [in] int iCol);
HRESULT Grid_OnLButtonDblClk([in] int iCellRow, [in] int iGridRow, [in] int iCol);
HRESULT Grid_OnPaste([in] int iCellRow, [in] int iGridRow, [in] int iCol);
HRESULT Grid_OnRowSelection([in] int iRow, [in] int iAction);
HRESULT Grid_OnDelete([in] int iRow);
};
[uuid(30000000-0000-0000-0000-000000000003), helpstring("FHGrid TypeLib"), version(1.0)] library FHGridLibrary
{
importlib("stdole32.tlb");
interface IGrid;
interface IGridEvents;
[uuid(30000000-0000-0000-0000-000000000000)] coclass FHGrid
{
interface IGrid;
[source] interface IGridEvents;
}
};
--- End code ---
Maybe I can fit a few headers ...
--- Code: ---//Grid.h
#ifndef GRID_H_INCLUDED
#define GRID_H_INCLUDED
#include "Interfaces.h"
#define MAX_CONNECTIONS 4
#define dwIdx(r,c) ((r-1)*pGridData->iCols+(c-1))
extern long g_lObjs;
extern long g_lLocks;
class FHGrid : public IGrid, public IConnectionPointContainer, public IConnectionPoint
{
public:
FHGrid(); //Constructor
virtual ~FHGrid(); //Destructor
//Iunknown Functions
virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void** ppv);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
//IGrid Interface Methods/Functions
virtual HRESULT STDMETHODCALLTYPE CreateGrid(HWND, BSTR, int, int, int, int, int, int, int, COLORREF, COLORREF, BSTR, int, int);
virtual HRESULT STDMETHODCALLTYPE SetRowCount(int, int);
virtual HRESULT STDMETHODCALLTYPE GetRowCount(int*);
virtual HRESULT STDMETHODCALLTYPE SetData(int, int, BSTR);
virtual HRESULT STDMETHODCALLTYPE GetData(int, int, BSTR*);
virtual HRESULT STDMETHODCALLTYPE FlushData(void);
virtual HRESULT STDMETHODCALLTYPE Refresh(void);
virtual HRESULT STDMETHODCALLTYPE GetVisibleRows(int*);
virtual HRESULT STDMETHODCALLTYPE GethGrid(HWND*);
virtual HRESULT STDMETHODCALLTYPE GethCell(int, int, HWND*);
virtual HRESULT STDMETHODCALLTYPE GethComboBox(int, HWND*);
virtual HRESULT STDMETHODCALLTYPE SetCellAttributes(int, int, COLORREF, COLORREF);
virtual HRESULT STDMETHODCALLTYPE DeleteRow(int);
//IConnectionPointContainer Interface Methods/Functions
virtual HRESULT STDMETHODCALLTYPE EnumConnectionPoints(IEnumConnectionPoints** ppEnum); //not implemented
virtual HRESULT STDMETHODCALLTYPE FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP);
// IConnectionPoint
virtual HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID* pIID); //not implemented
virtual HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer** ppCPC); //not implemented
virtual HRESULT STDMETHODCALLTYPE Advise(IUnknown* pUnknown, DWORD* pdwCookie);
virtual HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie);
virtual HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections** ppEnum); //not implemented
public:
HWND hWndCtrl;
IGridEvents** pISink;
long m_lRef;
};
class GridClassFactory : public IClassFactory
{
public:
GridClassFactory();
virtual ~GridClassFactory();
public:
//IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void**);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
//IclassFactory
virtual HRESULT STDMETHODCALLTYPE CreateInstance(LPUNKNOWN, REFIID, void**);
virtual HRESULT STDMETHODCALLTYPE LockServer(BOOL);
protected:
long m_lRef;
};
struct GridData
{
int iCtrlId;
HWND hParent;
HWND hGrid;
HWND hBase;
HWND hPane;
HWND hCtrlInCell;
int cx;
int cy;
HWND hHeader;
int iCols;
int iRows;
int iVisibleRows;
int iRowHeight;
int iPaneHeight;
int iEditedCellRow;
int iEditedRow;
int iEditedCol;
FHGrid* pComObj;
DWORD* pColWidths;
DWORD* pCellCtrlTypes;
HWND* pCellHandles;
TCHAR** pGridMemory;
COLORREF* pTextColor;
HBRUSH* pBackColor;
COLORREF* pCreatedColors;
HBRUSH* pCreatedBrushes;
HWND* pVButtons;
HWND* pCtrlHdls;
COLORREF iSelectionBackColor;
COLORREF iSelectionTextColor;
int blnRowSelected;
int iSelectedRow;
int iFontSize;
int iFontWeight;
HFONT hFont;
TCHAR szFontName[28];
};
void Initialize();
#endif
//End Grid.h
--- End code ---
Frederick J. Harris:
Interfaces.h
--- Code: ---//IFunctions.h
#ifndef INTERFACES_H_INCLUDED
#define INTERFACES_H_INCLUDED
const CLSID CLSID_FHGrid = {0x30000000, 0x0000, 0x0000, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} };
const IID IID_IFHGrid = {0x30000000, 0x0000, 0x0000, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01} };
const IID IID_IFHGridEvents = {0x30000000, 0x0000, 0x0000, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02} };
const IID LIBID_FHGrid = {0x30000000, 0x0000, 0x0000, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03} };
interface IGrid : IUnknown
{
virtual HRESULT STDMETHODCALLTYPE CreateGrid (HWND, BSTR, int, int, int, int, int, int, int, COLORREF, COLORREF, BSTR, int, int) = 0;
virtual HRESULT STDMETHODCALLTYPE SetRowCount (int, int ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetRowCount (int* ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetData (int, int, BSTR ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetData (int, int, BSTR* ) = 0;
virtual HRESULT STDMETHODCALLTYPE FlushData (void ) = 0;
virtual HRESULT STDMETHODCALLTYPE Refresh (void ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVisibleRows (int *iVisibleRows ) = 0;
virtual HRESULT STDMETHODCALLTYPE GethGrid (HWND* ) = 0;
virtual HRESULT STDMETHODCALLTYPE GethCell (int, int, HWND* ) = 0;
virtual HRESULT STDMETHODCALLTYPE GethComboBox (int, HWND* ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetCellAttributes (int, int, COLORREF, COLORREF ) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteRow (int ) = 0;
};
interface IGridEvents : IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Grid_OnKeyPress (int iKeyCode, int iKeyData, int iRow, int iCol, int* blnCancel ) = 0;
virtual HRESULT STDMETHODCALLTYPE Grid_OnKeyDown (int KeyCode, int iKeyData, int iCellRow, int iGridRow, int iCol, int* blnCancel ) = 0;
virtual HRESULT STDMETHODCALLTYPE Grid_OnLButtonDown (int iCellRow, int iGridRow, int iCol ) = 0;
virtual HRESULT STDMETHODCALLTYPE Grid_OnLButtonDblClk (int iCellRow, int iGridRow, int iCol ) = 0;
virtual HRESULT STDMETHODCALLTYPE Grid_OnPaste (int iCellRow, int iGridRow, int iCol ) = 0;
virtual HRESULT STDMETHODCALLTYPE Grid_OnRowSelection (int iRow, int iAction ) = 0;
virtual HRESULT STDMETHODCALLTYPE Grid_OnDelete (int iRow ) = 0;
};
#endif
--- End code ---
WinCode.h
--- Code: ---//WinCode.h
#ifndef WIN_CODE_H_INCLUDED
#define WIN_CODE_H_INCLUDED
#define GRID_CELL_CTRL_NONE 0
#define GRID_CELL_CTRL_EDIT 1
#define GRID_CELL_CTRL_COMBO 2
#define GRID_CELL_CTRL_CHECK 3
#define IDC_STATIC -1
#define MAX_COLORS 15
#define ID_PANE 1500
#define ID_HEADER 1505
#define ID_CELL 1600
#define IDC_EDIT 1605
#define IDC_COMBO 1705
#define dim(x) (sizeof(x) / sizeof(x[0]))
LRESULT CALLBACK fnGridProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK fnPaneProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK fnBaseProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK fnCellProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam);
struct WindowsEventArguments
{
HWND hWnd;
WPARAM wParam;
LPARAM lParam;
HINSTANCE hIns;
};
typedef WindowsEventArguments* lpWndEventArgs;
long fnGridProc_OnCreate (lpWndEventArgs Wea);
long fnGridProc_OnSize (lpWndEventArgs Wea);
long fnGridProc_OnHScroll (lpWndEventArgs Wea);
long fnGridProc_OnVScroll (lpWndEventArgs Wea);
long fnGridProc_OnKeyDown (lpWndEventArgs Wea);
long fnGridProc_OnCommand (lpWndEventArgs Wea);
long fnGridProc_OnDestroy (lpWndEventArgs Wea);
struct EVENTHANDLER
{
unsigned int iMsg;
long (*fnPtr)(lpWndEventArgs);
};
const EVENTHANDLER EventHandler[]=
{
{WM_CREATE, fnGridProc_OnCreate},
{WM_SIZE, fnGridProc_OnSize},
{WM_HSCROLL, fnGridProc_OnHScroll},
{WM_VSCROLL, fnGridProc_OnVScroll},
{WM_KEYDOWN, fnGridProc_OnKeyDown},
{WM_COMMAND, fnGridProc_OnCommand},
{WM_DESTROY, fnGridProc_OnDestroy}
};
#endif
--- End code ---
Registry.h
--- Code: ---BOOL SetKeyAndValue(const TCHAR* szKey, const TCHAR* szSubkey, const TCHAR* szValue);
void CLSIDToChar(const CLSID& clsid, TCHAR* szCLSID, int length);
LONG RecursiveDeleteKey(HKEY hKeyParent, const TCHAR* lpszKeyChild);
HRESULT RegisterServer(TCHAR* szModule, const CLSID& clsid, const TCHAR* szFriendlyName, const TCHAR* szVerIndProgID, const TCHAR* szProgID);
HRESULT UnregisterServer(const CLSID& clsid, const TCHAR* szVerIndProgID, const TCHAR* szProgID);
--- End code ---
Frederick J. Harris:
Grid.cpp
--- Code: ---//Grid.cpp
#define UNICODE
#define _UNICODE
//#define MYDEBUG
#include <windows.h>
#include <commctrl.h>
#include <objbase.h>
#include <ocidl.h>
#include <olectl.h>
#include <tchar.h>
#include <cstdio>
#include "Grid.h"
#include "WinCode.h"
extern WNDPROC fnEditWndProc;
extern HINSTANCE g_hModule;
extern long g_CtrlId;
#if defined MYDEBUG
extern FILE* fp;
#endif
FHGrid::FHGrid() //C++ Constructor for class FHGrid
{
#if defined MYDEBUG
printf(" Entering FHGrid Constructor!\n");
#endif
this->pISink=NULL, this->hWndCtrl=NULL, m_lRef=0;
#if defined MYDEBUG
printf(" this->m_lRef = %d\n", this->m_lRef);
#endif
InterlockedIncrement(&g_lObjs);
#if defined MYDEBUG
printf(" g_lObjs = %d\n", g_lObjs);
printf(" sizeof(*this) = %d\n",sizeof(*this));
#endif
#if defined MYDEBUG
printf(" Leaving FHGrid Constructor!\n");
#endif
}
HRESULT STDMETHODCALLTYPE FHGrid::QueryInterface(REFIID riid, void** ppv)
{
#if defined MYDEBUG
printf(" Entering FHGrid::QueryInterface()\n");
printf(" this = %d\n", this);
#endif
*ppv=0;
if(riid==IID_IUnknown)
*ppv=(IGrid*)this;
else if(riid==IID_IFHGrid)
*ppv=(IGrid*)this;
else if(riid==IID_IConnectionPointContainer)
*ppv=(IConnectionPointContainer*)this;
else if(riid==IID_IConnectionPoint)
*ppv=(IConnectionPoint*)this;
if(*ppv)
{
AddRef();
#if defined MYDEBUG
printf(" *ppv = %u\n",*ppv);
printf(" Leaving FHGrid::QueryInterface()\n");
#endif
return S_OK;
}
#if defined MYDEBUG
printf(" Leaving FHGrid::QueryInterface()\n");
#endif
return(E_NOINTERFACE);
}
ULONG STDMETHODCALLTYPE FHGrid::AddRef()
{
#if defined MYDEBUG
printf(" Entering FHGrid::AddRef()\n");
printf(" m_lRef = %d\n", m_lRef);
#endif
InterlockedIncrement(&m_lRef);
#if defined MYDEBUG
printf(" m_lRef = %d\n", m_lRef);
printf(" Leaving FHGrid::AddRef()\n");
#endif
return m_lRef;
}
ULONG STDMETHODCALLTYPE FHGrid::Release()
{
#if defined MYDEBUG
printf(" Entering FHGrid::Release()\n");
printf(" m_lRef = %d\n", m_lRef);
#endif
if(InterlockedDecrement(&m_lRef)==0)
{
#if defined MYDEBUG
printf(" m_lRef = %d\n", m_lRef);
printf(" Will Now Delete this ...\n");
printf(" this->pISink = %u\n\n",this->pISink);
printf(" i\t\t&this->pISink[i]\t\tthis->pISink[i]\n");
printf(" ============================================================\n");
for(size_t i=0; i<MAX_CONNECTIONS; i++)
printf(" %u\t\t%u\t\t\t\t%u\n",i,&this->pISink[i],this->pISink[i]);
printf(" \nLeaving FHGrid::Release()\n");
#endif
DestroyWindow(this->hWndCtrl);
CoTaskMemFree(this->pISink);
delete this;
return 0;
}
#if defined MYDEBUG
printf(" m_lRef = %d\n", m_lRef);
printf(" Leaving FHGrid::Release()\n");
#endif
return m_lRef;
}
HRESULT STDMETHODCALLTYPE FHGrid::CreateGrid(HWND hParent, BSTR strSetup, int x, int y, int cx, int cy, int iRows, int iCols, int iRowHt, COLORREF iSelBckClr, COLORREF iSelTxtClr, BSTR strFntNme, int iFntSize, int iFntWt)
{
GridData* pGridData=NULL;
DWORD dwStyle;
HWND hGrid=0;
GridData gd;
#ifndef UNICODE
return E_FAIL;
#endif
#if defined MYDEBUG
printf("Entering FHGrid::CreateGrid()\n");
_ftprintf(fp,_T("Entering FHGrid::CreateGrid()\n"));
_ftprintf(fp,_T(" this = %u\n"),this);
_ftprintf(fp,_T(" hParent = %u\n"),hParent);
_ftprintf(fp,_T(" strSetup = %s\n"),strSetup);
_ftprintf(fp,_T(" x = %d\n"),x);
_ftprintf(fp,_T(" y = %d\n"),y);
_ftprintf(fp,_T(" cx = %d\n"),cx);
_ftprintf(fp,_T(" cy = %d\n"),cy);
_ftprintf(fp,_T(" iRows = %d\n"),iRows);
_ftprintf(fp,_T(" iCols = %d\n"),iCols);
_ftprintf(fp,_T(" iRowHt = %d\n"),iRowHt);
_ftprintf(fp,_T(" iSelBckClr = %d\n"),iSelBckClr);
_ftprintf(fp,_T(" iSelTxtClr = %d\n"),iSelTxtClr);
_ftprintf(fp,_T(" strFntNme = %s\n"),strFntNme);
_ftprintf(fp,_T(" iFntSize = %d\n"),iFntSize);
_ftprintf(fp,_T(" iFntWt = %d\n"),iFntWt);
#endif
dwStyle = WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
gd.hParent = hParent;
gd.cx = cx;
gd.cy = cy;
gd.iRows = iRows;
gd.iCols = iCols;
gd.iRowHeight = iRowHt;
gd.iFontSize = iFntSize;
gd.iFontWeight = iFntWt;
gd.iSelectionBackColor = iSelBckClr;
gd.iSelectionTextColor = iSelTxtClr;
gd.iCtrlId=g_CtrlId;
wcscpy(gd.szFontName,strFntNme);
#if defined MYDEBUG
_ftprintf(fp,_T(" gd.szFontName = %s\n\n"),gd.szFontName);
_ftprintf(fp,_T(" g_CtrlId = %d\n"),g_CtrlId);
#endif
hGrid=CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,L"Grid",strSetup,dwStyle,x,y,cx,cy,hParent,(HMENU)g_CtrlId,g_hModule,&gd);
if(hGrid==0)
return E_FAIL;
g_CtrlId++;
this->hWndCtrl=hGrid;
pGridData=(GridData*)GetWindowLongPtr(hGrid,0);
if(!pGridData)
return E_FAIL;
pGridData->pComObj=this;
if(iSelBckClr==0)
pGridData->iSelectionBackColor=RGB(0x41,0x69,0xE1); // RGB_ROYALBLUE; // %RGB_ROYALBLUE = 0xE16941
if(iSelTxtClr==0)
pGridData->iSelectionTextColor=RGB(0x80,0x00,0x00); // RGB_MAROON; // %RGB_MAROON = 0x000080
this->SetCellAttributes(0,0,pGridData->iSelectionBackColor,pGridData->iSelectionTextColor);
SetFocus(hGrid);
#if defined MYDEBUG
_ftprintf(fp,_T(" hGrid = %u\n"),hGrid);
_ftprintf(fp,_T(" pGridData = %u\n"),pGridData);
_ftprintf(fp,_T(" pGridData->pComObj = %u\n"),pGridData->pComObj);
_ftprintf(fp,_T(" this->hWndCtrl = %u\n"),this->hWndCtrl);
_ftprintf(fp,_T(" &gd = %u\n"),&gd);
_ftprintf(fp,_T(" pGridData->blnRowSelected = %d\n"),pGridData->blnRowSelected);
_ftprintf(fp,_T(" pGridData->iSelectionBackColor = %0x\n"),pGridData->iSelectionBackColor);
_ftprintf(fp,_T(" pGridData->iSelectionTextColor = %0x\n"),pGridData->iSelectionTextColor);
_ftprintf(fp,_T("Leaving FHGrid::CreateGrid()\n\n"));
printf(" Leaving FHGrid::CreateGrid()\n");
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::SetRowCount(int iRowCount, int blnForce)
{
GridData* pGridData=NULL;
int iSize=0,blnFree=0;
HANDLE hHeap=0;
SCROLLINFO si;
int i;
#ifdef MYDEBUG
_ftprintf(fp,_T("Entering FHGrid::SetRowCount()\n"));
_ftprintf(fp,_T(" i blnFree\n"));
_ftprintf(fp,_T(" =================\n"));
#endif
pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
iSize=pGridData->iRows*pGridData->iCols;
hHeap=GetProcessHeap();
for(i=0; i<iSize; i++)
{
blnFree=HeapFree(hHeap,0,pGridData->pGridMemory[i]);
#ifdef MYDEBUG
_ftprintf(fp,_T(" %d\t%d\n"),i,blnFree);
#endif
}
blnFree=HeapFree(hHeap,0,pGridData->pGridMemory);
#ifdef MYDEBUG
_ftprintf(fp,_T("\n HeapFree(hHeap,0,pGridData->pGridMemory) = %d\n"),blnFree);
#endif
blnFree=HeapFree(hHeap,0,pGridData->pTextColor);
#ifdef MYDEBUG
_ftprintf(fp,_T(" HeapFree(hHeap,0,pGridData->pTextColor) = %d\n"),blnFree);
#endif
blnFree=HeapFree(hHeap,0,pGridData->pBackColor);
#ifdef MYDEBUG
_ftprintf(fp,_T(" HeapFree(hHeap,0,pGridData->pBackColor) = %d\n"),blnFree);
#endif
//Create A New Memory Block
if(iRowCount < pGridData->iVisibleRows)
{
#ifdef MYDEBUG
_ftprintf(fp,_T(" Got In Where iRowCount < iVisibleRows"));
#endif
iRowCount=pGridData->iVisibleRows+1;
}
iSize = iRowCount * pGridData->iCols;
pGridData->pGridMemory=(TCHAR**)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iSize*sizeof(void*));
if(!pGridData->pGridMemory)
return E_FAIL;
pGridData->iRows=iRowCount;
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize=sizeof(SCROLLINFO);
si.fMask=SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin=1;
si.nMax=pGridData->iRows;
si.nPage=pGridData->iVisibleRows;
si.nPos=1;
SetScrollInfo(this->hWndCtrl,SB_VERT,&si,TRUE);
pGridData->pTextColor=(COLORREF*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iSize*sizeof(void*));
#ifdef MYDEBUG
_ftprintf(fp,_T(" pGridData->pTextColor = %u\n"),pGridData->pTextColor);
#endif
if(!pGridData->pTextColor)
return E_FAIL;
pGridData->pBackColor=(HBRUSH*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iSize*sizeof(void*));
#ifdef MYDEBUG
_ftprintf(fp,_T(" pGridData->pBackColor = %u\n"),pGridData->pBackColor);
#endif
if(!pGridData->pBackColor)
return E_FAIL;
#ifdef MYDEBUG
_ftprintf(fp,_T("Leaving FHGrid::SetRowCount()\n\n"));
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::GetRowCount(int* iRowCount)
{
#ifdef MYDEBUG
_ftprintf(fp,_T("Entering FHGrid::GetRowCount()\n"));
#endif
GridData* pGridData=(GridData*)GetWindowLong(this->hWndCtrl,0);
if(pGridData)
{
*iRowCount=pGridData->iRows;
#ifdef MYDEBUG
_ftprintf(fp,_T(" *iRowCount = %d\n"),*iRowCount);
_ftprintf(fp,_T("Leaving FHGrid::GetRowCount()\n"));
#endif
return S_OK;
}
#ifdef MYDEBUG
_ftprintf(fp,_T(" *iRowCount = %d\n"),*iRowCount);
_ftprintf(fp,_T("Leaving FHGrid::GetRowCount()\n"));
#endif
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE FHGrid::SetData(int iRow, int iCol, BSTR strData)
{
GridData* pGridData=NULL;
HANDLE hHeap=NULL;
int iIndex;
#ifdef MYDEBUG
printf("Called FHGrid::SetData()\n");
_ftprintf(fp,_T("Entering FHGrid::SetData()\n"));
_ftprintf(fp,_T(" this = %u\n"),this);
_ftprintf(fp,_T(" iRow = %d\n"),iRow);
_ftprintf(fp,_T(" iCol = %d\n"),iCol);
_ftprintf(fp,_T(" strData = %s\n"),strData);
#endif
pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(pGridData)
{
if(iRow && iRow<=pGridData->iRows)
{
if(iCol && iCol<=pGridData->iCols)
{
iIndex=dwIdx(iRow,iCol);
hHeap=GetProcessHeap();
#ifdef MYDEBUG
_ftprintf(fp,_T(" iIndex = %d\n"),iIndex);
_ftprintf(fp,_T(" pGridData->pGridMemory[iIndex] = %u\n"),pGridData->pGridMemory[iIndex]);
_ftprintf(fp,_T(" pGridData->pGridMemory[iIndex] = %s\n"),pGridData->pGridMemory[iIndex]);
#endif
if(pGridData->pGridMemory[iIndex]==NULL)
{
#ifdef MYDEBUG
_ftprintf(fp,_T(" Got In Where Memory Is Null\n"));
#endif
pGridData->pGridMemory[iIndex]=(TCHAR*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(SysStringLen(strData)*sizeof(TCHAR))+sizeof(TCHAR));
if(pGridData->pGridMemory[iIndex])
_tcscpy(pGridData->pGridMemory[iIndex],strData);
else
return S_FALSE;
}
else
{
if(wcscmp(pGridData->pGridMemory[iIndex],strData)==0) // Both Strings Are The Same, So No Need To Replace. Therefore, Just Return.
{
#ifdef MYDEBUG
_ftprintf(fp,_T(" Got In Where Parameter Is Same As Memory, So Just Return.\n"));
#endif
return S_OK;
}
else
{
#ifdef MYDEBUG
_ftprintf(fp,_T(" Got In Where We'll Allocate Memory And Copy Parameter To it.\n"));
#endif
HeapFree(hHeap,0,pGridData->pGridMemory[iIndex]);
pGridData->pGridMemory[iIndex]=(TCHAR*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(SysStringLen(strData)*sizeof(TCHAR))+sizeof(TCHAR));
if(pGridData->pGridMemory[iIndex])
_tcscpy(pGridData->pGridMemory[iIndex],strData);
else
return S_FALSE;
}
}
}
else
return S_FALSE;
}
else
return S_FALSE;
}
else
return S_FALSE;
#ifdef MYDEBUG
_ftprintf(fp,_T("Leaving FHGrid::SetData()\n\n"));
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::GetData(int iRow, int iCol, BSTR* strData)
{
#ifdef MYDEBUG
printf("Called FHGrid::GetData()\n");
#endif
GridData* pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(pGridData)
{
if(iRow<=pGridData->iRows && iRow>0 && iCol<=pGridData->iCols && iCol>0)
{
int iIndex=dwIdx(iRow,iCol);
SysReAllocString(strData,pGridData->pGridMemory[iIndex]);
return S_OK;
}
}
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE FHGrid::FlushData()
{
GridData* pGridData=NULL;
HWND hGrid;
#ifdef MYDEBUG
printf("Called FHGrid::FlushData()\n");
_ftprintf(fp,_T(" Entering FHGrid::FlushData()\n"));
#endif
hGrid=this->hWndCtrl;
pGridData=(GridData*)GetWindowLongPtr(hGrid,0);
#ifdef MYDEBUG
_ftprintf(fp,_T(" hGrid = %u\n"),hGrid);
_ftprintf(fp,_T(" pGridData = %u\n"),pGridData);
#endif
if(pGridData->hCtrlInCell)
{
#ifdef MYDEBUG
_ftprintf(fp,_T(" Got In Where pGridData->hCtrlInCell = TRUE!\n"));
#endif
int iLen=GetWindowTextLength(pGridData->hCtrlInCell);
HANDLE hHeap=GetProcessHeap();
TCHAR* pZStr=(TCHAR*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(iLen+1)*sizeof(TCHAR));
if(pZStr)
{
GetWindowText(pGridData->hCtrlInCell,pZStr,iLen+1);
BSTR strData=SysAllocString(pZStr);
this->SetData(pGridData->iEditedRow,pGridData->iEditedCol,strData);
SetWindowLongPtr(pGridData->hCtrlInCell,GWLP_WNDPROC,(LONG_PTR)fnEditWndProc);
SetParent(pGridData->hCtrlInCell,hGrid);
SetWindowPos(pGridData->hCtrlInCell,HWND_BOTTOM,0,0,0,0,SWP_HIDEWINDOW);
pGridData->hCtrlInCell=0;
this->Refresh();
}
else
{
return E_FAIL;
}
}
#ifdef MYDEBUG
_ftprintf(fp,_T(" Leaving FHGrid::FlushData()\n"));;
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::Refresh()
{
int iRows,iCols,iCountCells,iReturn,iIdx;
GridData* pGridData=NULL;
TCHAR* pText=NULL;
SCROLLINFO si;
#ifdef MYDEBUG
printf("Called FHGrid::Refresh()\n");
_ftprintf(fp,_T("Entering FHGrid::Refresh()\n"));
#endif
pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
#ifdef MYDEBUG
_ftprintf(fp,_T(" pGridData = %u\n"),pGridData);
#endif
if(pGridData)
{
iRows = pGridData->iVisibleRows;
iCols = pGridData->iCols;
iCountCells =iRows*iCols;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_POS;
iReturn = GetScrollInfo(this->hWndCtrl,SB_VERT,&si);
#ifdef MYDEBUG
_ftprintf(fp,_T(" iReturn = %d\n"),iReturn);
_ftprintf(fp,_T(" pGridData->iVisibleRows = %d\n"),pGridData->iVisibleRows);
_ftprintf(fp,_T(" pGridData->iCols = %d\n"),pGridData->iCols);
_ftprintf(fp,_T(" iCountCells = %d\n"),iCountCells);
_ftprintf(fp,_T(" si.nPos = %d\n\n"),si.nPos);
_ftprintf(fp,_T(" i pGridData->pCellHandles[i] pGridData->pGridMemory[i] pText pGridData->pBackColor[iIdx] pGridData->pTextColor[iIdx]\n"));
_ftprintf(fp,_T(" ==============================================================================================================================\n"));
#endif
if(iReturn)
{
for(int i=0; i<iCountCells; i++)
{
iIdx=iCols*(si.nPos-1)+i;
SetWindowLongPtr(pGridData->pCellHandles[i],0,(LONG_PTR)pGridData->pGridMemory[iIdx]);
SetWindowLongPtr(pGridData->pCellHandles[i],2*sizeof(void*),(LONG_PTR)pGridData->pTextColor[iIdx]);
SetWindowLongPtr(pGridData->pCellHandles[i],3*sizeof(void*),(LONG_PTR)pGridData->pBackColor[iIdx]);
InvalidateRect(pGridData->pCellHandles[i],NULL, TRUE);
pText=(TCHAR*)pGridData->pGridMemory[i];
#ifdef MYDEBUG
_ftprintf
(
fp,
_T(" %d\t\t%u\t\t\t%u\t\t\t%s\t\t\t0x%x\t\t\t0x%x\n"),
i,pGridData->pCellHandles[i],pGridData->pGridMemory[i],pText,pGridData->pBackColor[iIdx],pGridData->pTextColor[iIdx]
);
#endif
}
}
}
#ifdef MYDEBUG
_ftprintf(fp,_T("Leaving FHGrid::Refresh()\n"));
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::GetVisibleRows(int* iVisibleRows)
{
GridData* pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(pGridData)
{
*iVisibleRows=pGridData->iVisibleRows;
return S_OK;
}
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE FHGrid::GethGrid(HWND* hWnd)
{
GridData* pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(pGridData)
{
*hWnd=pGridData->hGrid;
return S_OK;
}
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE FHGrid::GethCell(int iRow, int iCol, HWND* hCell)
{
GridData* pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(pGridData)
{
if(iRow<=pGridData->iRows && iRow)
{
if(iCol<=pGridData->iCols && iCol)
{
int iIndex=dwIdx(iRow,iCol);
*hCell=pGridData->pCellHandles[iIndex];
return S_OK;
}
}
}
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE FHGrid::GethComboBox(int iCol, HWND* hCombo)
{
#ifdef MYDEBUG
_ftprintf(fp,_T("Entering FHGrid::GethComboBox()\n"));
#endif
GridData* pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(pGridData->pCellCtrlTypes[iCol-1]==GRID_CELL_CTRL_COMBO)
*hCombo=(HWND)pGridData->pCtrlHdls[iCol-1];
else
return E_FAIL;
#ifdef MYDEBUG
_ftprintf(fp,_T(" *hCombo = %u\n"),*hCombo);
_ftprintf(fp,_T("Leaving FHGrid::GethComboBox()\n\n"));
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::SetCellAttributes(int iRow, int iCol, COLORREF iBackColor, COLORREF iTextColor)
{
int iIdx=0,i=0,blnFound=0;
GridData* pGridData=NULL;
#if defined MYDEBUG
printf("Called FHGrid::SetCellAttributes()\n");
_ftprintf(fp,_T(" Entering FHGrid::SetCellAttributes()\n"));
_ftprintf(fp,_T(" iRow = %u\n"),iRow);
_ftprintf(fp,_T(" iCol = %u\n"),iCol);
_ftprintf(fp,_T(" iBackColor = 0x%x\n"),iBackColor);
_ftprintf(fp,_T(" iTextColor = 0x%x\n"),iTextColor);
#endif
pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
if(iRow && iCol)
{
#if defined MYDEBUG
_ftprintf(fp,_T(" Got In Where iRow And iCol Are Both Something!\n"));
#endif
iIdx=dwIdx(iRow,iCol);
pGridData->pTextColor[iIdx] = iTextColor;
#if defined MYDEBUG
_ftprintf(fp,_T(" iIdx = %u\n"),iIdx);
#endif
}
else
{
#if defined MYDEBUG
_ftprintf(fp,_T(" Got In Where Either iRow Or iCol Ain't Shit!\n"));
#endif
}
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData->iCols = %d\n"),pGridData->iCols);
_ftprintf(fp,_T(" iIdx = %u\n"),iIdx);
_ftprintf(fp,_T(" pGridData->pTextColor = %d\n"),pGridData->pTextColor);
_ftprintf(fp,_T(" pGridData->pTextColor[iIdx] = 0x%x\n"),pGridData->pTextColor[iIdx]);
_ftprintf(fp,_T(" pGridData->pCellHandles[iIdx] = %u\n"),pGridData->pCellHandles[iIdx]);
_ftprintf(fp,_T(" pGridData->pCreatedColors[0] = %u\n"),pGridData->pCreatedColors[0]);
_ftprintf(fp,_T(" pGridData->pCreatedBrushes[0] = %u\n\n"),pGridData->pCreatedBrushes[0]);
_ftprintf(fp,_T(" i pGridData->pCreatedColors[i] iBackColor\n"));
_ftprintf(fp,_T(" =============================================================\n"));
#endif
//pGridMemory As Dword Ptr 'Will be storing ZStr Ptrs here. We need a
//pTextColor As Dword Ptr 'Will be storing RGB values here, i.e., %Red, %Blue, etc
//pBackColor As Dword Ptr 'Will be storing HBRUSHs here. May be zero for default brush.
//pCreatedColors As Dword Ptr 'Colors so far asked for by user per grid instance, e.g., %Red, %Yellow, %Blue, etc.
//pCreatedBrushes As Dword Ptr 'Will be storing created HBRUSHs here. Accumulate them. Numbers such as &HA0556789
for(i=1; i<=pGridData->pCreatedColors[0]; i++)
{
#if defined MYDEBUG
_ftprintf(fp,_T(" %d\t\t0x%x\t\t0x%x\n"),i,pGridData->pCreatedColors[i],iBackColor);
#endif
if(pGridData->pCreatedColors[i]==iBackColor)
{
blnFound=TRUE;
break;
}
}
#if defined MYDEBUG
_ftprintf(fp,_T(" blnFound = %d\n"),blnFound);
_ftprintf(fp,_T(" i = %d\n"),i);
#endif
if(blnFound) // Color Was Already Created
{
if(iRow && iCol)
{
pGridData->pBackColor[iIdx]=pGridData->pCreatedBrushes[i];
}
#if defined MYDEBUG
_ftprintf(fp,_T("\n"));
_ftprintf(fp,_T(" Got In Where blnFound = %True!\n"));
_ftprintf(fp,_T(" pGridData->pCreatedBrushes[i] = 0x%x\n"),pGridData->pCreatedBrushes[i]);
#endif
}
else // Need To Create Brush And Store It
{
#if defined MYDEBUG
_ftprintf(fp,_T("\n"));
_ftprintf(fp,_T(" Got In Where blnFound = False!\n"));
_ftprintf(fp,_T(" pGridData->pCreatedBrushes[0] = %d << Before\n"),pGridData->pCreatedBrushes[0]);
#endif
if((int)pGridData->pCreatedBrushes[0]<MAX_COLORS) // Test to see if pGridData->pCreatedBrushes[0]
{ // is less than 15, i.e., %MAX_COLORS
int iCreatedBrushes=(int)pGridData->pCreatedBrushes[0];
iCreatedBrushes++;
pGridData->pCreatedBrushes[0]=(HBRUSH)iCreatedBrushes;
int iCreatedColors=(int)pGridData->pCreatedColors[0];
iCreatedColors++;
pGridData->pCreatedColors[0]=(COLORREF)iCreatedColors;
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData->pCreatedColors[0] = %d\n"),pGridData->pCreatedColors[0]);
_ftprintf(fp,_T(" Will Be Able To Create Another Brush!\n"));
#endif
}
else
{
#if defined MYDEBUG
_ftprintf(fp,_T(" Can't Create Another Brush!\n"));
_ftprintf(fp,_T(" Leaving IGrid_SetCellAttributes()\n"));
#endif
return E_FAIL; // We've already created 15 brushes (Or Whatever MAX_COLORS Is).
}
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData->pCreatedBrushes[0] = %d << After\n"),pGridData->pCreatedBrushes[0]);
#endif
pGridData->pCreatedBrushes[(int)pGridData->pCreatedBrushes[0]] = CreateSolidBrush(iBackColor);
pGridData->pCreatedColors[pGridData->pCreatedColors[0]] = iBackColor;
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData->pCreatedBrushes[(int)pGridData->pCreatedBrushes[0]] = 0x%x\n"),pGridData->pCreatedBrushes[(int)pGridData->pCreatedBrushes[0]]);
#endif
if(iRow && iCol)
{
pGridData->pBackColor[iIdx] = pGridData->pCreatedBrushes[(int)pGridData->pCreatedBrushes[0]];
#if defined MYDEBUG
_ftprintf(fp,_T(" Have Just Assigned A Newly Created Brush To pBackColor[] At correct Location\n"));
_ftprintf(fp,_T(" pGridData->pBackColor[iIdx] = 0x%x\n"),pGridData->pBackColor[iIdx]);
#endif
}
}
#if defined MYDEBUG
_ftprintf(fp,_T(" Leaving FHGrid::SetCellAttributes()\n\n"));
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE FHGrid::DeleteRow(int iRow)
{
#if defined MYDEBUG
_ftprintf(fp,_T("Entering FHGrid::DeleteRow()\n"));
#endif
GridData* pGridData=(GridData*)GetWindowLongPtr(this->hWndCtrl,0);
int iSize=(pGridData->iRows-1)*pGridData->iCols-1;
int iStart=dwIdx(iRow,1);
int iCols=pGridData->iCols;
for(int i=iStart; i<=iSize; i++)
{
pGridData->pGridMemory[i] = pGridData->pGridMemory[i+iCols];
pGridData->pTextColor[i] = pGridData->pTextColor[i+iCols];
pGridData->pBackColor[i] = pGridData->pBackColor[i+iCols];
}
iStart=dwIdx(pGridData->iRows,1);
for(int i=iStart; i<iStart+iCols; i++)
{
pGridData->pGridMemory[i] = 0;
pGridData->pTextColor[i] = 0;
pGridData->pBackColor[i] = 0;
}
for(int i=1; i<=iCols; i++)
pGridData->pComObj->SetCellAttributes(iRow,i,pGridData->iSelectionBackColor,pGridData->iSelectionTextColor);
#if defined MYDEBUG
_ftprintf(fp,_T("Leaving FHGrid::DeleteRow()\n"));
#endif
return S_OK;
}
HRESULT FHGrid::EnumConnectionPoints(IEnumConnectionPoints** ppEnum)
{
#ifdef MYDEBUG
printf("Called FHGrid::EnumConnectionPoints()\n");
#endif
return E_NOTIMPL;
}
HRESULT FHGrid::FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP)
{
#ifdef MYDEBUG
printf("Entering FHGrid::FindConnectionPoint()\n");
printf(" this = %u\n",this);
printf(" *ppCP = %u\n",*ppCP);
#endif
HRESULT hr=this->QueryInterface(IID_IConnectionPoint,(void**)ppCP);
if(SUCCEEDED(hr))
{
#ifdef MYDEBUG
printf(" QueryInterface(IID_IConnectionPoint) Succeeded!\n");
printf(" *ppCP = %u\n",*ppCP);
printf("Leaving FHGrid::FindConnectionPoint()\n");
#endif
return hr;
}
else
{
#ifdef MYDEBUG
printf(" QueryInterface(IID_IConnectionPoint) Failed!\n");
printf("Leaving FHGrid::FindConnectionPoint()\n");
#endif
return E_NOINTERFACE;
}
}
HRESULT FHGrid::GetConnectionInterface(IID* pIID)
{
return E_NOTIMPL;
}
HRESULT FHGrid::GetConnectionPointContainer(IConnectionPointContainer** ppCPC)
{
return E_NOTIMPL;
}
HRESULT FHGrid::Advise(IUnknown* pUnkSink, DWORD* pdwCookie)
{
int blnFoundOpenSlot=FALSE,i;
#ifdef MYDEBUG
printf(" Entering FHGrid::Advise()\n");
printf(" this = %u\n",this);
printf(" pUnkSink = %u\n\n",pUnkSink);
printf(" i &this->pISink[i] this->pISink[i]\n");
printf(" ===========================================\n");
#endif
for(i=0; i<MAX_CONNECTIONS; i++)
{
#ifdef MYDEBUG
printf(" %d\t%u\t\t\t\t%d\n",i,&this->pISink[i],this->pISink[i]);
#endif
if(this->pISink[i]==0)
{
blnFoundOpenSlot=TRUE;
break;
}
}
if(blnFoundOpenSlot)
{
HRESULT hr=pUnkSink->QueryInterface(IID_IFHGridEvents,(void**)&this->pISink[i]);
if(SUCCEEDED(hr))
{
#ifdef MYDEBUG
printf(" i = %d\n",i);
printf(" pUnkSink->QueryInterface() For Client Sink Succeeded!\n");
printf(" this->pISink[i] = %u\n",this->pISink[i]);
printf(" Leaving FHGrid::Advise()\n");
#endif
*pdwCookie=(DWORD)i;
return S_OK;
}
else
{
#ifdef MYDEBUG
printf(" pUnkSink->QueryInterface() For Client Sink Failed!\n");
#endif
}
}
else
{
#ifdef MYDEBUG
printf(" Couldn't Find An Open Slot To Store Connection!\n");
#endif
}
#ifdef MYDEBUG
printf(" Leaving FHGrid::Advise()\n");
#endif
return E_FAIL;
}
HRESULT FHGrid::Unadvise(DWORD dwCookie)
{
#ifdef MYDEBUG
printf("Entering FHGrid::Unadvise()\n");
printf(" dwCookie = %u\n",dwCookie);
#endif
IUnknown* pIUnknown=this->pISink[dwCookie];
pIUnknown->Release();
this->pISink[dwCookie]=0;
#ifdef MYDEBUG
printf(" pIUnknown = %u\n",pIUnknown);
printf("Leaving FHGrid::Unadvise()\n");
#endif
return NOERROR;
}
HRESULT FHGrid::EnumConnections(IEnumConnections** ppEnum)
{
return E_NOTIMPL;
}
FHGrid::~FHGrid() //C++ Destructor for class FHGrid
{
#if defined MYDEBUG
printf(" Entering FHGrid Destructor!\n");
printf(" g_lObjs = %d\n", g_lObjs);
#endif
InterlockedDecrement(&g_lObjs);
#if defined MYDEBUG
printf(" g_lObjs = %d\n", g_lObjs);
printf(" Leaving FHGrid Destructor!\n");
#endif
}
// Grid Class Factory
GridClassFactory::GridClassFactory()
{
#if defined MYDEBUG
printf(" Entering GridClassFactory Constructor!\n");
#endif
m_lRef=0;
#if defined MYDEBUG
printf(" this->m_lRef = %d\n", this->m_lRef);
#endif
#if defined MYDEBUG
printf(" Leaving GridClassFactory Constructor!\n");
#endif
}
GridClassFactory::~GridClassFactory() //GridClassFactory Destructor
{
#if defined MYDEBUG
printf(" Entering GridClassFactory Destructor!\n");
#endif
#if defined MYDEBUG
printf(" this->m_lRef = %d\n", this->m_lRef);
#endif
#if defined MYDEBUG
printf(" Leaving GridClassFactory Destructor!\n");
#endif
}
HRESULT STDMETHODCALLTYPE GridClassFactory::QueryInterface(REFIID riid, void** ppv)
{
printf(" Entering GridClassFactory::QueryInterface()\n");
*ppv=0;
if(riid==IID_IUnknown || riid==IID_IClassFactory)
*ppv=this;
#if defined MYDEBUG
printf(" *ppv = %u\n", *ppv);
#endif
if(*ppv)
{
AddRef();
printf(" Leaving GridClassFactory::QueryInterface()\n");
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE GridClassFactory::AddRef()
{
#if defined MYDEBUG
printf(" Entering GridClassFactory::AddRef()!\n");
printf(" this->m_lRef = %d\n", this->m_lRef);
#endif
InterlockedIncrement(&m_lRef);
#if defined MYDEBUG
printf(" this->m_lRef = %d\n", this->m_lRef);
printf(" Leaving GridClassFactory::AddRef()!\n");
#endif
return this->m_lRef;
}
ULONG STDMETHODCALLTYPE GridClassFactory::Release()
{
#if defined MYDEBUG
printf(" Entering GridClassFactory::Release()!\n");
printf(" this->m_lRef = %d\n", this->m_lRef);
#endif
InterlockedDecrement(&m_lRef);
if(this->m_lRef==0)
{
printf(" this->m_lRef = %d\n", this->m_lRef);
delete this;
#if defined MYDEBUG
printf(" GridClassFactory Has Been Destroyed!\n");
printf(" Leaving GridClassFactory::Release()!\n");
#endif
return 0;
}
#if defined MYDEBUG
printf(" this->m_lRef = %d\n", this->m_lRef);
printf(" Leaving GridClassFactory::Release()!\n");
#endif
return m_lRef;
}
HRESULT STDMETHODCALLTYPE GridClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
{
FHGrid* pGrid=NULL;
HRESULT hr;
#if defined MYDEBUG
printf(" Entering GridClassFactory::CreateInstance()\n");
#endif
*ppvObj=0;
pGrid=new FHGrid;
#if defined MYDEBUG
printf(" pGrid = %u\n",pGrid);
printf(" sizeof(*pGrid) = %d\n",sizeof(*pGrid));
#endif
if(pGrid==NULL)
return E_OUTOFMEMORY;
hr=pGrid->QueryInterface(riid,ppvObj);
if(FAILED(hr))
delete pGrid;
else
{
pGrid->pISink=(IGridEvents**)CoTaskMemAlloc(MAX_CONNECTIONS*sizeof(void*));
#if defined MYDEBUG
printf(" pGrid->pISink = %u\n",pGrid->pISink);
printf(" pGrid->pISink[0] = %u\n",pGrid->pISink[0]);
printf(" pGrid->pISink[1] = %u\n",pGrid->pISink[1]);
printf(" pGrid->pISink[2] = %u\n",pGrid->pISink[2]);
printf(" pGrid->pISink[3] = %u\n",pGrid->pISink[3]);
#endif
if(pGrid->pISink==NULL)
return E_OUTOFMEMORY;
else
{
pGrid->pISink[0]=(IGridEvents*)0;
pGrid->pISink[1]=(IGridEvents*)NULL;
pGrid->pISink[2]=(IGridEvents*)NULL;
pGrid->pISink[3]=(IGridEvents*)NULL;
#if defined MYDEBUG
printf(" pGrid->pISink = %u\n",pGrid->pISink);
printf(" pGrid->pISink[0] = %u\n",pGrid->pISink[0]);
printf(" pGrid->pISink[1] = %u\n",pGrid->pISink[1]);
printf(" pGrid->pISink[2] = %u\n",pGrid->pISink[2]);
printf(" pGrid->pISink[3] = %u\n",pGrid->pISink[3]);
#endif
}
}
#if defined MYDEBUG
printf(" Leaving GridClassFactory::CreateInstance()\n");
#endif
return hr;
}
HRESULT STDMETHODCALLTYPE GridClassFactory::LockServer(BOOL fLock)
{
if(fLock)
InterlockedIncrement(&g_lLocks);
else
InterlockedDecrement(&g_lLocks);
return S_OK;
}
void Initialize()
{
INITCOMMONCONTROLSEX uCC;
TCHAR szClassName[16];
short int iRet=0;
WNDCLASSEX wc;
#if defined MYDEBUG
printf(" Entering Initialize()\n");
#endif
uCC.dwSize = sizeof(uCC); // Initialize Common Controls (need header control).
uCC.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&uCC);
_tcscpy(szClassName,_T("Grid")); // Register Grid Class
wc.lpszClassName = szClassName;
wc.lpfnWndProc = fnGridProc;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(void*);
wc.hInstance = g_hModule;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.hIconSm = NULL;
iRet = RegisterClassEx(&wc);
#if defined MYDEBUG
printf(" RegisterClassEx(Grid) = %d\n",iRet);
#endif
_tcscpy(szClassName,_T("Pane")); // Register Pane Class
wc.lpszClassName = szClassName;
wc.lpfnWndProc = fnPaneProc;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(void*);
wc.hInstance = g_hModule;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.hIconSm = NULL;
iRet = RegisterClassEx(&wc);
#if defined MYDEBUG
printf(" RegisterClassEx(Pane) = %d\n",iRet);
#endif
_tcscpy(szClassName,_T("Base")); // Register Pane Class
wc.lpszClassName = szClassName;
wc.lpfnWndProc = fnBaseProc;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hModule;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.hIconSm = NULL;
iRet = RegisterClassEx(&wc);
#if defined MYDEBUG
printf(" RegisterClassEx(Pane) = %d\n",iRet);
#endif
_tcscpy(szClassName,_T("Cell")); // Register Cell Class
wc.lpszClassName = szClassName;
wc.lpfnWndProc = fnCellProc;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 4*sizeof(void*);
wc.hInstance = g_hModule;
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.hIconSm = NULL;
iRet = RegisterClassEx(&wc);
#if defined MYDEBUG
printf(" RegisterClassEx(Cell) = %d\n",iRet);
printf(" Leaving Initialize()\n");
#endif
}
//End Grid.cpp
--- End code ---
Frederick J. Harris:
WinCode.cpp will have to be broken up. I'll try 1st half ...
--- Code: ---#define UNICODE
#define _UNICODE
#include <windows.h>
#include <commctrl.h>
#include <objbase.h>
#include <ocidl.h>
#include <olectl.h>
#include <cstdio>
#include <tchar.h>
#include "Strings.h"
#include "Grid.h"
#include "WinCode.h"
//#define MYDEBUG
#if defined MYDEBUG
extern FILE* fp;
#endif
WNDPROC fnEditWndProc; // edit control subclass
long fnGridProc_OnCreate(lpWndEventArgs Wea)
{
int iEndRectHt,iHalf,iRemainder,iDifference,iNewGridHt;
int iCols=0,iFlds=0,iHdlCount=0,iCtr=0,iSize=0;
CREATESTRUCT* pCreateStruct=NULL;
GridData* pGridData1=NULL;
GridData* pGridData2=NULL;
String* strParseData;
HANDLE hHeap=NULL;
TCHAR szText[64];
String strSetup;
HDITEM hdrItem;
DWORD dwStyle;
HWND hCell;
HDC hDC;
RECT rc;
#if defined MYDEBUG
_ftprintf(fp,_T(" Entering fnGridProc_OnCreate()\n"));
#endif
pCreateStruct=(CREATESTRUCT*)Wea->lParam;
Wea->hIns=pCreateStruct->hInstance;
pGridData1=(GridData*)pCreateStruct->lpCreateParams;
strSetup=(TCHAR*)pCreateStruct->lpszName;
#if defined MYDEBUG
_ftprintf(fp,_T(" Wea->hWnd = %u\n"),Wea->hWnd);
_ftprintf(fp,_T(" pCreateStruct = %u\n"),pCreateStruct);
_ftprintf(fp,_T(" pGridData1 = %u\n"),pGridData1);
_ftprintf(fp,_T(" strSetup.lpStr() = %s\n"),strSetup.lpStr());
_ftprintf(fp,_T(" pCreateStruct->hwndParent = %u\n"),pCreateStruct->hwndParent);
_ftprintf(fp,_T(" pCreateStruct->x = %d\n"),pCreateStruct->x);
_ftprintf(fp,_T(" pCreateStruct->y = %d\n"),pCreateStruct->y);
_ftprintf(fp,_T(" pCreateStruct->cx = %d\n"),pCreateStruct->cx);
_ftprintf(fp,_T(" pCreateStruct->cy = %d\n"),pCreateStruct->cy);
_ftprintf(fp,_T(" pCreateStruct->hMenu = %u\n"),pCreateStruct->hMenu);
_ftprintf(fp,_T(" pGridData1->cx = %d\n"),pGridData1->cx);
_ftprintf(fp,_T(" pGridData1->iRows = %d\n"),pGridData1->iRows);
_ftprintf(fp,_T(" pGridData1->iCols = %d\n"),pGridData1->iCols);
_ftprintf(fp,_T(" pGridData1->iRowHeight = %d\n"),pGridData1->iRowHeight);
_ftprintf(fp,_T(" pGridData1->szFontName = %s\n"),pGridData1->szFontName);
_ftprintf(fp,_T(" pGridData1->iFontSize = %d\n"),pGridData1->iFontSize);
_ftprintf(fp,_T(" pGridData1->iFontWeight = %d\n"),pGridData1->iFontWeight);
#endif
pGridData1->hGrid=Wea->hWnd;
GetClientRect(Wea->hWnd,&rc);
iCols=strSetup.ParseCount(_T(','));
#if defined MYDEBUG
_ftprintf(fp,_T(" rc.left = %d\n"),rc.left);
_ftprintf(fp,_T(" rc.top = %d\n"),rc.top);
_ftprintf(fp,_T(" rc.right = %d\n"),rc.right);
_ftprintf(fp,_T(" rc.bottom = %d\n"),rc.bottom);
_ftprintf(fp,_T(" iCols = %d\n"),iCols);
#endif
if(iCols!=pGridData1->iCols)
return -1;
hHeap=GetProcessHeap();
if(!hHeap)
return -1;
pGridData2=(GridData*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(GridData));
if(!pGridData2)
return -1;
SetWindowLongPtr(Wea->hWnd,0,(LONG_PTR)pGridData2);
pGridData1->blnRowSelected=FALSE;
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData2 = %u\n"),pGridData2);
#endif
memcpy(pGridData2,pGridData1,sizeof(GridData));
iNewGridHt=pCreateStruct->cy;
iHalf=pGridData2->iRowHeight/2;
iRemainder=rc.bottom % pGridData2->iRowHeight;
#ifdef MYDEBUG
_ftprintf(fp,_T(" iNewGridHt = %d\n"),iNewGridHt);
_ftprintf(fp,_T(" pGridData2->iRowHeight = %d\n"),pGridData2->iRowHeight);
_ftprintf(fp,_T(" iHalf = %d\n"),iHalf);
_ftprintf(fp,_T(" iRemainder = %d\n"),iRemainder);
#endif
if(iRemainder>=iHalf)
{
iDifference=pGridData2->iRowHeight-iRemainder;
iEndRectHt=rc.bottom+(pGridData2->iRowHeight-iRemainder);
}
else
{
iDifference=-iRemainder;
iEndRectHt=rc.bottom-iRemainder;
}
iNewGridHt=iNewGridHt+iDifference;
#ifdef MYDEBUG
_ftprintf(fp,_T(" iEndRectHt = %d\n"),iEndRectHt);
_ftprintf(fp,_T(" iDifference = %d\n"),iDifference);
_ftprintf(fp,_T(" iNewGridHt = %d\n"),iNewGridHt);
#endif
pGridData2->iVisibleRows=(iEndRectHt-pGridData2->iRowHeight)/pGridData2->iRowHeight;
if(pGridData2->iRows<pGridData2->iVisibleRows)
pGridData2->iRows=pGridData2->iVisibleRows+1;
pGridData2->iPaneHeight=(pGridData2->iVisibleRows+1)*pGridData2->iRowHeight;
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData2->hParent = %u\n"),pGridData2->hParent);
_ftprintf(fp,_T(" pGridData2->hGrid = %u\n"),pGridData2->hGrid);
_ftprintf(fp,_T(" pGridData2->iCtrlId = %d\n"),pGridData2->iCtrlId);
_ftprintf(fp,_T(" pGridData2->cx = %u\n"),pGridData2->cx);
_ftprintf(fp,_T(" pGridData2->cy = %u\n"),pGridData2->cy);
_ftprintf(fp,_T(" pGridData2->iRows = %d\n"),pGridData2->iRows);
_ftprintf(fp,_T(" pGridData2->iCols = %d\n"),pGridData2->iCols);
_ftprintf(fp,_T(" pGridData2->iRowHeight = %d\n"),pGridData2->iRowHeight);
_ftprintf(fp,_T(" pGridData2->szFontName = %s\n"),pGridData2->szFontName);
_ftprintf(fp,_T(" pGridData2->iFontSize = %d\n"),pGridData2->iFontSize);
_ftprintf(fp,_T(" pGridData2->iFontWeight = %d\n"),pGridData2->iFontWeight);
_ftprintf(fp,_T(" pGridData2->iVisibleRows = %d\n"),pGridData2->iVisibleRows);
_ftprintf(fp,_T(" pGridData2->iPaneHeight = %d\n"),pGridData2->iPaneHeight);
_ftprintf(fp,_T(" pGridData2->blnRowSelected = %d\n\n"),pGridData2->blnRowSelected);
_ftprintf(fp,_T(" i strParseData(i) \n"));
_ftprintf(fp,_T(" ============================\n"));
#endif
strParseData=new String[iCols];
strSetup.Parse(strParseData,_T(','));
for(unsigned int i=0; i<iCols; i++)
{
strParseData[i].Trim();
#if defined MYDEBUG
_ftprintf(fp,_T(" %d\t%s\n"),i,strParseData[i].lpStr());
#endif
}
pGridData2->pColWidths=(DWORD*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(DWORD)*(iCols+1));
if(!pGridData2->pColWidths)
goto CleanUp;
#if defined MYDEBUG
_ftprintf(fp,_T("\n pGridData2->pColWidths = %u\n"),pGridData2->pColWidths);
#endif
pGridData2->hBase=CreateWindowEx(0,_T("Base"),_T(""),WS_CHILD|WS_VISIBLE,0,0,0,0,Wea->hWnd,(HMENU)1499,Wea->hIns,0);
pGridData2->hPane=CreateWindowEx(0,_T("Pane"),_T(""),WS_CHILD|WS_VISIBLE,0,0,0,0,pGridData2->hBase,(HMENU)ID_PANE,Wea->hIns,0);
dwStyle=WS_CHILD | WS_BORDER | WS_VISIBLE | HDS_HOTTRACK | HDS_HORZ;
pGridData2->hHeader=CreateWindowEx(0,WC_HEADER,_T(""),dwStyle,0,0,0,0,pGridData2->hPane,(HMENU)ID_HEADER,Wea->hIns,0);
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData2->hBase = %u\n"),pGridData2->hBase);
_ftprintf(fp,_T(" pGridData2->hPane = %u\n"),pGridData2->hPane);
_ftprintf(fp,_T(" pGridData2->hHeader = %u\n"),pGridData2->hHeader);
_ftprintf(fp,_T(" HDF_LEFT = %d\n"),HDF_LEFT);
_ftprintf(fp,_T(" HDF_CENTER = %d\n"),HDF_CENTER);
_ftprintf(fp,_T(" HDF_RIGHT = %d\n\n"),HDF_RIGHT);
#endif
SetWindowLongPtr(pGridData2->hPane,0,(LONG_PTR)pGridData2);
pGridData2->pCellCtrlTypes=(DWORD*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iCols*sizeof(DWORD)); // no extra bytes allocated here, so its zero based
if(!pGridData2->pCellCtrlTypes)
goto CleanUp;
pGridData2->pCtrlHdls=(HWND*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iCols*sizeof(HWND*)); // no extra bytes allocated here either, so its zero based
if(!pGridData2->pCtrlHdls)
goto CleanUp;
hdrItem.mask=HDI_FORMAT | HDI_WIDTH | HDI_TEXT;
#if defined MYDEBUG
_ftprintf(fp,_T(" i\tstrFieldData[0]\tpGridData2->pColWidths[i]\tstrFieldData[1]\tstrFieldData[2]\tstrFieldData[3]\tpPos[i]\t\tpGridData2->pCellCtrlTypes[i]\n"));
_ftprintf(fp,_T(" ============================================================================================================================================\n"));
#endif
int* pPos=(int*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iCols*sizeof(int)); // and no extra bytes allocated here
if(!pPos)
goto CleanUp;
pGridData2->pColWidths[iCols]=0;
for(unsigned int i=0; i<iCols; i++)
{
iFlds=strParseData[i].ParseCount(_T(':'));
String* strFieldData=new String[iFlds];
strParseData[i].Parse(strFieldData,_T(':'));
pGridData2->pColWidths[i]=(DWORD)strFieldData[0].iVal();
pGridData2->pColWidths[iCols]=pGridData2->pColWidths[iCols]+pGridData2->pColWidths[i];
hdrItem.cxy=pGridData2->pColWidths[i];
_tcscpy(szText,strFieldData[1].lpStr()); // here's the line that's crashing it!!!!!!!!!!!!!!!!!!!!
hdrItem.pszText=szText;
hdrItem.cchTextMax=_tcslen(szText);
hdrItem.fmt=0;
if(strFieldData[2]==_T("<"))
hdrItem.fmt=HDF_LEFT;
else
{
if(strFieldData[2]==_T("^"))
hdrItem.fmt=HDF_CENTER;
else
hdrItem.fmt=HDF_RIGHT;
}
hdrItem.fmt=hdrItem.fmt|HDF_STRING;
Header_InsertItem(pGridData2->hHeader,i,&hdrItem);
if(i)
pPos[i]=pPos[i-1]+pGridData2->pColWidths[i-1];
if(strFieldData[3]==_T("none"))
pGridData2->pCellCtrlTypes[i]=0;
else
{
if(strFieldData[3]==_T("edit"))
pGridData2->pCellCtrlTypes[i]=1;
else
{
if(strFieldData[3]==_T("combo"))
pGridData2->pCellCtrlTypes[i]=2;
if(strFieldData[3]==_T("check"))
pGridData2->pCellCtrlTypes[i]=0;
}
}
#if defined MYDEBUG
_ftprintf
(
fp,
_T(" %d\t%s\t\t%u\t\t\t\t%s\t%s\t\t%s\t\t%d\t\t%u\n"),
i,strFieldData[0].lpStr(),pGridData2->pColWidths[i],strFieldData[1].lpStr(),strFieldData[2].lpStr(),strFieldData[3].lpStr(),pPos[i],pGridData2->pCellCtrlTypes[i]
);
#endif
delete [] strFieldData;
}
#if defined MYDEBUG
_ftprintf(fp,_T("\n"));
_ftprintf(fp,_T(" iCols = %u\n\n"),iCols);
_ftprintf(fp,_T(" i\tpGridData2->pColWidths[i]\n"));
_ftprintf(fp,_T(" ================================\n"));
for(unsigned int i=0; i<=iCols; i++)
_ftprintf(fp,_T(" %u\t\t%u\n"),i,pGridData2->pColWidths[i]);
_ftprintf(fp,_T("\n"));
_ftprintf(fp,_T(" i\tpGridData2->pCtrlHdls[i]\n"));
_ftprintf(fp,_T(" ==================================\n"));
#endif
int blnEditCreated = 0;
int iCboCtr = 0;
for(unsigned int i=0; i<iCols; i++)
{
// Edit Control In Column
if(pGridData2->pCellCtrlTypes[i]==GRID_CELL_CTRL_EDIT)
{
if(blnEditCreated==FALSE)
{
dwStyle = WS_CHILD | ES_AUTOHSCROLL;
pGridData2->pCtrlHdls[i]=CreateWindowEx(0,_T("edit"),_T(""),dwStyle,0,0,0,0,Wea->hWnd,(HMENU)IDC_EDIT,Wea->hIns,0);
pGridData2->hCtrlInCell=pGridData2->pCtrlHdls[i];
blnEditCreated=TRUE;
}
else
{
pGridData2->pCtrlHdls[i]=pGridData2->hCtrlInCell;
}
}
// Combo Box In Column
if(pGridData2->pCellCtrlTypes[i]==GRID_CELL_CTRL_COMBO)
{
dwStyle=WS_CHILD | CBS_DROPDOWNLIST | WS_VSCROLL; //Or %CBS_NOINTEGRALHEIGHT
pGridData2->pCtrlHdls[i]=CreateWindowEx(0,_T("combobox"),_T(""),dwStyle,0,0,0,0,Wea->hWnd,(HMENU)(IDC_COMBO+iCboCtr),Wea->hIns,0);
iCboCtr++;
}
#if defined MYDEBUG
_ftprintf(fp,_T(" %u\t\t%u\n"),i,pGridData2->pCtrlHdls[i]);
#endif
}
pGridData2->hCtrlInCell=0; // DANGER!!!!!! Addition! I don't know why this needes to be initially set?
#if defined MYDEBUG
_ftprintf(fp,_T("\n"));
_ftprintf(fp,_T(" pGridData2->pColWidths[iCols] = %d\n"),pGridData2->pColWidths[iCols]);
_ftprintf(fp,_T("\n"));
#endif
MoveWindow(Wea->hWnd,pCreateStruct->x,pCreateStruct->y,pCreateStruct->cx,iNewGridHt,FALSE);
MoveWindow(pGridData2->hBase,12,0,rc.right-12,pGridData2->iPaneHeight,FALSE);
MoveWindow(pGridData2->hPane,0,0,pGridData2->pColWidths[iCols],pGridData2->iPaneHeight,FALSE);
MoveWindow(pGridData2->hHeader,0,0,pGridData2->pColWidths[iCols],pGridData2->iRowHeight,TRUE);
delete [] strParseData;
pGridData2->pVButtons=(HWND*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(pGridData2->iVisibleRows+1)*sizeof(void*));
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData2->pVButtons = %u\n\n"),pGridData2->pVButtons);
_ftprintf(fp,_T(" i\tpGridData2->pVButtons[i]\n"));
_ftprintf(fp,_T(" ===================================\n"));
#endif
if(!pGridData2->pVButtons)
goto CleanUp;
else
{
for(unsigned int i=0; i<=pGridData2->iVisibleRows; i++)
{
pGridData2->pVButtons[i]=CreateWindowEx(0,_T("button"),_T(""),WS_CHILD|WS_VISIBLE|BS_FLAT,0,pGridData2->iRowHeight*i,12,pGridData2->iRowHeight,Wea->hWnd,(HMENU)(20000+i),Wea->hIns,0);
#if defined MYDEBUG
_ftprintf(fp,_T(" %u\t%u\n"),i,pGridData2->pVButtons[i]);
#endif
}
}
// Now gonna try to create font ...
#if defined MYDEBUG
_ftprintf(fp,_T("\n Now Gonna Try To Create Font...\n"));
_ftprintf(fp,_T(" pGridData2->szFontName = %s\n"),pGridData2->szFontName);
#endif
if(pGridData2->szFontName)
{
hDC=GetDC(Wea->hWnd);
pGridData2->hFont=CreateFont(-1*(pGridData2->iFontSize*GetDeviceCaps(hDC,LOGPIXELSY))/72,0,0,0,pGridData2->iFontWeight,0,0,0,ANSI_CHARSET,0,0,DEFAULT_QUALITY,0,pGridData2->szFontName);
#if defined MYDEBUG
_ftprintf(fp,_T(" pGridData2->hFont = %u\n\n"),pGridData2->hFont);
#endif
ReleaseDC(Wea->hWnd,hDC);
}
else
goto CleanUp;
iHdlCount=pGridData2->iCols*pGridData2->iVisibleRows;
pGridData2->pCellHandles=(HWND*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iHdlCount*sizeof(void*));
#if defined MYDEBUG
_ftprintf(fp,_T(" iCols = %d\n"),iCols);
_ftprintf(fp,_T(" pGridData2->iCols = %u\n"),pGridData2->iCols);
_ftprintf(fp,_T(" iHdlCount = %d\n"),iHdlCount);
_ftprintf(fp,_T(" pGridData2->pCellHandles = %u\n"),pGridData2->pCellHandles);
#endif
if(!pGridData2->pCellHandles)
goto CleanUp;
dwStyle=WS_CHILD | WS_VISIBLE | WS_BORDER;
#if defined MYDEBUG
_ftprintf(fp,_T("\n"));
_ftprintf(fp,_T(" i\t\tj\tiPos(j)\tyLoc\thCell\n"));
_ftprintf(fp,_T(" =============================================================\n"));
#endif
for(int i=0; i<pGridData2->iVisibleRows; i++)
{
for(int j=0; j<pGridData2->iCols; j++)
{
hCell=CreateWindowEx(0,_T("Cell"),_T(""),dwStyle,pPos[j],pGridData2->iRowHeight+(i*pGridData2->iRowHeight),pGridData2->pColWidths[j],pGridData2->iRowHeight,pGridData2->hPane,(HMENU)(ID_CELL+iCtr),Wea->hIns,0);
pGridData2->pCellHandles[iCtr]=hCell;
SetWindowLongPtr(hCell,sizeof(void*),(LONG_PTR)pGridData2->hFont); // 4 for 32 bit; 8 for 64 bit
#if defined MYDEBUG
_ftprintf(fp,_T(" %d\t\t%d\t%u\t%d\t%u\n"),i,j,pPos[j],pGridData2->iRowHeight+(i*pGridData2->iRowHeight),hCell);
#endif
iCtr++;
}
}
// grid memory
iSize=pGridData2->iCols*pGridData2->iRows;
pGridData2->pGridMemory=(TCHAR**)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iSize*sizeof(void*));
if(!pGridData2->pGridMemory)
goto CleanUp;
pGridData2->pTextColor=(COLORREF*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iSize*sizeof(void*));
if(!pGridData2->pTextColor)
goto CleanUp;
pGridData2->pBackColor=(HBRUSH*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,iSize*sizeof(void*));
if(!pGridData2->pBackColor)
goto CleanUp;
pGridData2->pCreatedColors=(COLORREF*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(MAX_COLORS+1)*sizeof(void*));
if(!pGridData2->pCreatedColors)
goto CleanUp;
pGridData2->pCreatedBrushes=(HBRUSH*)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,(MAX_COLORS+1)*sizeof(void*));
if(!pGridData2->pCreatedBrushes)
goto CleanUp;
#ifdef MYDEBUG
_ftprintf(fp,_T(" iSize = %d\n"),iSize);
_ftprintf(fp,_T(" pGridData2->pGridMemory = %u\n"),pGridData2->pGridMemory);
#endif
//Done
if(pPos)
HeapFree(hHeap,0,pPos);
#if defined MYDEBUG
_ftprintf(fp,_T(" Everything Allocated OK!\n"));
_ftprintf(fp,_T(" Leaving fnGridProc_OnCreate()\n\n"));
#endif
return 0;
CleanUp:
if(pGridData2->pColWidths)
{
HeapFree(hHeap,0,pGridData2->pColWidths);
pGridData2->pColWidths=NULL;
}
if(pGridData2->pCellCtrlTypes)
{
HeapFree(hHeap,0,pGridData2->pCellCtrlTypes);
pGridData2->pCellCtrlTypes=NULL;
}
if(pGridData2->pCtrlHdls)
{
HeapFree(hHeap,0,pGridData2->pCtrlHdls);
pGridData2->pCtrlHdls=NULL;
}
if(pPos)
HeapFree(hHeap,0,pPos);
if(pGridData2->pVButtons)
{
HeapFree(hHeap,0,pGridData2->pVButtons);
pGridData2->pVButtons=NULL;
}
if(pGridData2->hFont)
DeleteObject(pGridData2->hFont);
if(pGridData2->pCellHandles)
HeapFree(hHeap,0,pGridData2->pCellHandles);
if(pGridData2->pGridMemory)
HeapFree(hHeap,0,pGridData2->pGridMemory);
if(pGridData2->pTextColor)
HeapFree(hHeap,0,pGridData2->pTextColor);
if(pGridData2->pBackColor)
HeapFree(hHeap,0,pGridData2->pBackColor);
if(pGridData2->pCreatedColors)
HeapFree(hHeap,0,pGridData2->pCreatedColors);
if(pGridData2->pCreatedBrushes)
HeapFree(hHeap,0,pGridData2->pCreatedBrushes);
#if defined MYDEBUG
_ftprintf(fp,_T(" Leaving fnGridProc_OnCreate()\n\n"));
#endif
return 0;
}
long fnGridProc_OnSize(lpWndEventArgs Wea)
{
GridData* pGridData=NULL;
SCROLLINFO si;
int iCols;
#if defined MYDEBUG
_ftprintf(fp,_T(" Entering fnGridProc_OnSize()\n"));
_ftprintf(fp,_T(" Wea->hWnd = %u\n"),Wea->hWnd);
#endif
pGridData=(GridData*)GetWindowLongPtr(Wea->hWnd,0);
iCols=pGridData->iCols;
#ifdef MYDEBUG
_ftprintf(fp,_T(" pGridData = %u\n"),pGridData);
_ftprintf(fp,_T(" iCols = %d\n"),iCols);
#endif
//Set Up Horizontal Scrollbar
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;
si.nMin = 0;
si.nMax = pGridData->pColWidths[iCols];
si.nPage = pGridData->cx-33; // 33 is the width of vert
si.nPos = 0; // btns + width scroll bar + window edge
SetScrollInfo(Wea->hWnd,SB_HORZ,&si,TRUE);
#ifdef MYDEBUG
_ftprintf(fp,_T(" Horizontal Scrollbar....\n"));
_ftprintf(fp,_T(" si.nMin = %d\n"),si.nMin);
_ftprintf(fp,_T(" si.nMax = %d\n"),si.nMax);
_ftprintf(fp,_T(" si.nPos = %d\n"),si.nPos);
#endif
//Set Up Verticle Scrollbar
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = 1;
si.nMax = pGridData->iRows;
si.nPage = pGridData->iVisibleRows;
si.nPos = 1;
SetScrollInfo(Wea->hWnd,SB_VERT,&si,TRUE);
#ifdef MYDEBUG
_ftprintf(fp,_T(" Verticle Scrollbar....\n"));
_ftprintf(fp,_T(" si.nMin = %d\n"), si.nMin);
_ftprintf(fp,_T(" si.nMax = %d\n"), si.nMax);
_ftprintf(fp,_T(" si.nPos = %d\n"), si.nPos);
_ftprintf(fp,_T(" Leaving %WM_SIZE Case\n"));
_ftprintf(fp,_T(" Leaving fnGridProc_OnSize()\n\n"));
#endif
return 0;
}
long fnGridProc_OnHScroll(lpWndEventArgs Wea)
{
GridData* pGridData=NULL;
int iCols,iScrollPos;
SCROLLINFO si;
#if defined MYDEBUG
_ftprintf(fp,_T("Entering fnGridProc_OnHScroll()\n"));
_ftprintf(fp,_T(" Wea->hWnd = %u\n"),Wea->hWnd);
#endif
ZeroMemory(&si, sizeof(SCROLLINFO));
pGridData = (GridData*)GetWindowLongPtr(Wea->hWnd,0);
iCols = pGridData->iCols;
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
GetScrollInfo(pGridData->hGrid,SB_HORZ,&si);
iScrollPos=si.nPos;
#ifdef MYDEBUG
_ftprintf(fp,_T(" Before Adjustments\n"));
_ftprintf(fp,_T(" si.nMin = %d\n"), si.nMin);
_ftprintf(fp,_T(" si.nMax = %d\n"), si.nMax);
_ftprintf(fp,_T(" si.nPos = %d\n"), si.nPos);
#endif
switch(LOWORD(Wea->wParam))
{
case SB_LINELEFT:
{
if(si.nPos > si.nMin)
si.nPos=si.nPos-50;
break;
}
case SB_PAGELEFT:
{
si.nPos = si.nPos - si.nPage;
break;
}
case SB_LINERIGHT:
{
if(si.nPos<si.nMax)
si.nPos=si.nPos+50;
break;
}
case SB_PAGERIGHT:
{
si.nPos = si.nPos + si.nPage;
break;
}
case SB_THUMBTRACK:
{
si.nPos=si.nTrackPos;
break;
}
}
si.fMask = SIF_POS;
SetScrollInfo(pGridData->hGrid,SB_HORZ,&si,TRUE);
GetScrollInfo(pGridData->hGrid,SB_HORZ,&si);
if(iScrollPos!=si.nPos)
{
if(si.nPos==0)
SetWindowPos(pGridData->hPane,HWND_TOP,0,0,pGridData->pColWidths[iCols],pGridData->iPaneHeight,SWP_SHOWWINDOW);
else
SetWindowPos(pGridData->hPane,HWND_TOP,-si.nPos,0,pGridData->pColWidths[iCols],pGridData->iPaneHeight,SWP_SHOWWINDOW);
}
#ifdef MYDEBUG
_ftprintf(fp,_T(" After All Adjustments\n"));
_ftprintf(fp,_T(" si.nMin = %d\n"),si.nMin);
_ftprintf(fp,_T(" si.nMax = %d\n"),si.nMax);
_ftprintf(fp,_T(" si.nPos = %d\n"),si.nPos);
_ftprintf(fp,_T(" Leaving %WM_HSCROLL Case\n"));
_ftprintf(fp,_T("Leaving fnGridProc_OnHScroll()\n\n"));
#endif
return 0;
}
long fnGridProc_OnVScroll(lpWndEventArgs Wea)
{
GridData* pGridData=NULL;
int iCols,iScrollPos;
SCROLLINFO si;
HWND hCell;
#if defined MYDEBUG
_ftprintf(fp,_T("Entering fnGridProc_OnVScroll()\n"));
_ftprintf(fp,_T(" Wea->hWnd = %u\n"),Wea->hWnd);
#endif
ZeroMemory(&si, sizeof(SCROLLINFO));
pGridData = (GridData*)GetWindowLongPtr(Wea->hWnd,0);
pGridData->pComObj->FlushData();
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
GetScrollInfo(pGridData->hGrid,SB_VERT,&si);
iScrollPos=si.nPos;
#ifdef MYDEBUG
_ftprintf(fp,_T(" Before Adjustments\n"));
_ftprintf(fp,_T(" si.nMin = %d\n"), si.nMin);
_ftprintf(fp,_T(" si.nMax = %d\n"), si.nMax);
_ftprintf(fp,_T(" si.nPos = %d\n"), si.nPos);
_ftprintf(fp,_T(" pGridData->hGrid = %u\n"), pGridData->hGrid);
_ftprintf(fp,_T(" pGridData = %u\n"), pGridData);
#endif
switch(LOWORD(Wea->wParam)) // this originally didn't work
{
case SB_LINEUP:
{
if(si.nPos > si.nMin)
si.nPos=si.nPos-1;
break;
}
case SB_PAGEUP:
{
si.nPos = si.nPos - si.nPage;
break;
}
case SB_LINEDOWN:
{
if(si.nPos<si.nMax)
si.nPos=si.nPos+1;
break;
}
case SB_PAGEDOWN:
{
si.nPos = si.nPos + si.nPage;
break;
}
case SB_THUMBTRACK:
{
si.nPos=si.nTrackPos;
break;
}
}
si.fMask=SIF_POS;
SetScrollInfo(pGridData->hGrid,SB_VERT,&si,TRUE);
GetScrollInfo(pGridData->hGrid,SB_VERT,&si);
if(iScrollPos!=si.nPos)
{
int iNum,iLast;
iNum=pGridData->iCols*(si.nPos-1);
iLast=(pGridData->iCols * pGridData->iVisibleRows) - 1;
for(int i=0; i<=iLast; i++)
{
hCell=pGridData->pCellHandles[i];
SetWindowLongPtr(hCell,0,(LONG_PTR)pGridData->pGridMemory[iNum]);
SetWindowLongPtr(hCell,2*sizeof(void*),(LONG_PTR)pGridData->pTextColor[iNum]);
SetWindowLongPtr(hCell,3*sizeof(void*),(LONG_PTR)pGridData->pBackColor[iNum]);
iNum++;
}
}
InvalidateRect(pGridData->hGrid,NULL,TRUE);
#ifdef MYDEBUG
_ftprintf(fp,_T(" After All Adjustments\n"));
_ftprintf(fp,_T(" si.nMin = %d\n"),si.nMin);
_ftprintf(fp,_T(" si.nMax = %d\n"),si.nMax);
_ftprintf(fp,_T(" si.nPos = %d\n"),si.nPos);
_ftprintf(fp,_T(" Leaving %WM_VSCROLL Case\n"));
_ftprintf(fp,_T("Leaving fnGridProc_OnVScroll()\n\n"));
#endif
return 0;
}
--- End code ---
Navigation
[0] Message Index
[#] Next page
Go to full version