Delphi 7 component changes, fixes and important notes
-----------------------------------------------------

- no need to stop thread timer when closing FormStatus (it stops automatically)

- in "mame_roms.el" (and others), the first two chars in rom name are (space at 2nd position!):
     "0 " -> game ROM
     "1 " -> Device ROM
     "2 " -> Bios ROM
     "3 " -> Game CHD file
     "4 " -> Bios CHD file
     "5 " -> Device CHD file

- var iUpdatedGames (uMain.pas) is used to count changed games and show game names+system after games scan... for debugging only

- variable "NumGamesChanged" in "uMain.CallScanGames()" function is used to reset the filters
  ...could it be used to display how many games have changed ? maybe

- Graphics32 component GR32.pas fixed by me to open image files without crashing; new "or fmShareDenyNone" in the
  following function... procedure TCustomBitmap32.LoadFromFile(const FileName: string);

- Delphi 7 components fixed by me due to Delphi limitations or bugs under Windows 7/ Windows 8:
    (modified Delphi 7 source files are included with EL's source code)
    - update Jan 21, 2014: there are other changes but I can't remember...
    - TProgressBar: flickering under Windows Vista / Windows 7 / Windows 8
    - TComboBoxEx: Item height list was limited to 16 pixels (it should be the same height as the
                   assigned ImageList)
    - TImagelist: - icon size limitation removed
                  - native 32-bit support (alpha blend)
    - TTrackBar: ticks flickering or something like that (can't remember)
    - TShellTreeView: there is a missing "override" and a wrong ClearItems in TCustomShellTreeView.Destroy

- procedure uMain.PopulateMachineToUsePopupMenu(const SoftwareName: String);
  it load supported machines into a popup menu... not used anymore (July 23, 2015)

- delete uMain.LoadSoftwareListXML; function ??????????? it parses "softlist.xml" files directly into the games list 
  without creating games list but it's too slow...


{ TCustomShellTreeView }
...
TCustomShellTreeView = class(TCustomTreeView, IShellCommandVerb)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override; //$$jp shellctrl.pas 26.08.2007: missing "override"
procedure Refresh(Node: TTreeNode);
...

destructor TCustomShellTreeView.Destroy;
begin
//$$jp: ClearItems;
//$$jp: raises EInvalidOperation and access-violations (shellctrl.pas 26.08.2007)
FRootFolder.Free;
inherited;
end;

- function uMain.ELV_PopulateSystems() adds "all systems" (create games list, scan games) and no item is hidden (only "ghosted")
  and MAWS/Progetto EMMA is only added in "categories settings" to hide it from categories popup menus... (when ELV has checkbboxes)

- ALL projects must have this to override Delphi's ugly hand cursor with the nice Windows hand cursor
  Screen.Cursors[crHandPoint]:= LoadCursor(0, IDC_HAND);

- remember to set Ctl3D property to TRUE on all TAdvGroupBox components (Ctl3D is off by default)

- remember, AdvGroupBox's CheckBox "click" event is set to "OnCheckBoxClick", not "OnClick" event

- 2013: new Delphi 7 change: IniFiles.pas "function TStringHash.HashOf(const Key: string): Cardinal;" it's in
  asm optimized language now. not sure if it makes this feature faster, but it works without any bugs

- November 2013: added a "Ghosted" property in TEasyItem (public section) to check for ghosted items easily (EasyListview.pas)

- changes in EasyListView.pas (July 26, 2015): implemented multi-line captions for report view (small icon view)

  -> procedure TEasyViewSmallIconItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString;
                                                    var RectArray: TEasyRectArrayObject);

  -> function TEasyViewSmallIconItem.PaintTextLineCount(Item: TEasyItem; Column: TEasyColumn): Integer;


- fixes for EasyListView.pas 

  -> fix the StateImageIndex = -1 and avoid it painting a space instead of moving the text back...
  file: "EasyListView.pas"
  procedure TEasyViewSmallIconItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas;
                                            const Caption: WideString; var RectArray: TEasyRectArrayObject);

  -> replace this line:
     if PaintStateImage and  ((StateImageIndex > -1) or (GetImageList(Column, Item, eikState) <> nil)) then

  -> by this one:
     if PaintStateImage and  ((StateImageIndex > -1) and (GetImageList(Column, Item, eikState) <> nil)) then

- another fix for EasyListView... no alpha blend, with gradient and rounded corners (factor 2 max)
  add the following into
  
  "procedure TEasyViewItem.PaintSelectionRect()
   begin
     if OwnerListview.Selection.Gradient and not OwnerListview.Selection.AlphaBlend then
        begin
          if OwnerListview.Selection.RoundRect then
             begin
               FillGradient(LocalSelWindowClippedRect.Left, LocalSelWindowClippedRect.Top, LocalSelWindowClippedRect.Right,
               LocalSelWindowClippedRect.Bottom {- 1}, GradientTop, GradientBottom,
               LocalSelWindowClippedRect.Top+1, LocalSelWindowClippedRect.Bottom-2, ACanvas);
               ACanvas.Pen.Color:= ACanvas.Brush.Color;
               ACanvas.Brush.Style:= bsClear;
               ACanvas.RoundRect(LocalSelRect.Left, LocalSelRect.Top, LocalSelRect.Right, LocalSelRect.Bottom,
                                 OwnerListview.Selection.RoundRectRadius, OwnerListview.Selection.RoundRectRadius);
             end
          else
             begin
               FillGradient(LocalSelWindowClippedRect.Left, LocalSelWindowClippedRect.Top, LocalSelWindowClippedRect.Right,
               LocalSelWindowClippedRect.Bottom {- 1}, GradientTop, GradientBottom,
               LocalSelWindowClippedRect.Top+1, LocalSelWindowClippedRect.Bottom-2, ACanvas);
               ACanvas.FrameRect(LocalSelRect);
             end;
        end;
   end;

- cosmetic fix for EasyListview... focus rect is now a solid frame see Listview.pas
  procedure TEasyViewItem.PaintFocusRect(Item: TEasyItem; Column: TEasyColumn; const Caption: WideString; RectArray: TEasyRectArrayObject; ACanvas: TCanvas);

- EasyListView.pas ................................................
  TEasyViewItem.PaintAlphaBlendedRoundRect(ACanvas: TCanvas;
                 AlphaColor: TColor; GradientBottom: TColor; GradientTop: TColor;
                 var LocalSelWindowClippedRect: TRect; var Rgn: HRGN);

- TEasyViewItem.PaintSelectionRect() where it draws the non-alphablend gradient!!!!!!
  ... ACanvas.FrameRect(LocalSelRect);

- March 23, 2015 (EasyListView.pas): implemented "HideCaption" property to Tiles view mode, so check box can appear left side, vertically centered!!!!

  procedure TEasyViewTileItem.ItemRectArray(Item: TEasyItem; Column: TEasyColumn; ACanvas: TCanvas; const Caption: WideString;
                                            var RectArray: TEasyRectArrayObject);


- Delphi 2010 new routines!! "source\Win32\rtl\common\IOUtils.pas"...
  http://stackoverflow.com/questions/1642220/getting-size-of-a-file-in-d2010
  Maybe certain routines could be updated for Delphi 7... must check files

- function to scroll text to the top (RichEdit)

procedure ScrollMemoDown(Memo: TMemo);
begin
  SendMessage(Memo.Handle,{ HWND of the Memo Control }
    WM_VSCROLL,    { Windows Message }
    SB_PAGEDOWN,   { Scroll Command }
    0)             { Not Used }
end;


procedure ScrollMemoUp(Memo: TMemo);
begin      
  SendMessage(Memo.Handle, { HWND of the Memo Control }
    WM_VSCROLL,    { Windows Message }
    SB_PAGEUP,     { Scroll Command }
    0);            { Not Used }
end;


// Example, Beispiel:

procedure TForm1.Button1Click(Sender: TObject);
begin  
  ScrollMemoDown(Memo1);
end;

- Change height of items with 32 and 16 icon size BcDrawModule "onMeasureMenuItem" event
  Jan 21, 2014: some items are already treated there!

- check procedure TEasyViewItem.PaintAlphaBlendedRoundRect() to learn how to do alpha blend and
   a round rect region with alpha blending.... ^-^

- [MAYBE ??] try to change EasyListView to make dual gradient selection bar
              .... on EasyListView / MPCommonUtilities.FillGradient

- [MAYBE!!!] updates for Delphi XE7 2015 (not all are necessary)
  -> Create the project and all screens from scratch to avoid old properties/events from Delphi 7
     ... but copy and paste all custom functions, procedures and components events (.pas) 
  -> [MAYBE] remove GraphicEx library from project since D2012 have PNG/GIF/JPG .dcu libraries
  -> [MAYBE] change edit boxes that have a button (browse, select...) by the new buttoned edit box component
  -> [MAYBE] remove "madCollections" (madExcept). this library only facilitates to find where the crash happens.
     Delphi 2012 an newer seems to have a more detailed debugger (not sure though)
  -> is FastMM still necessary ? I think so... need to check the one bundled with XE7
  -> ask ZipForge author to give me a nag-free build compatible with Delphi xE7... without that annoying nag screen
     (no source code required!)...
  -> [MAYBE ?] support aero glass interface

- convert to UTF-8 from WideString (src\osd\sdl\sdlmain.c)

//============================================================
//  wstring_from_utf8
//============================================================

WCHAR *wstring_from_utf8(const char *utf8string)
{
	int char_count;
	WCHAR *result;

	// convert MAME string (UTF-8) to UTF-16
	char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0);
	result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result));
	if (result != NULL)
		MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);

	return result;
}

//============================================================
//  utf8_from_wstring
//============================================================

char *utf8_from_wstring(const WCHAR *wstring)
{
	int char_count;
	char *result;

	// convert UTF-16 to MAME string (UTF-8)
	char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL);
	result = (char *)osd_malloc_array(char_count * sizeof(*result));
	if (result != NULL)
		WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL);

	return result;
}
