Author Topic: Late binding to DLL / Call DWORD equiv / (for Ray)  (Read 1534 times)

0 Members and 1 Guest are viewing this topic.

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 3719
    • Oxygen Basic
Re: Late binding to DLL / Attaching prototypes
« Reply #15 on: March 11, 2018, 07:58:00 AM »
Sure,

) as int, at @messagebox

Even without a return type specified it will return an integer (in eax/rax)
Code: [Select]
'/*
'2018-03-11 T 15:55:30
'prototype overlay
uses corewin
'Create protype with default values for MessageBox
! messagebox(
  sys hwnd=0,
  char*text="",
  char*title="OxygenBasic",
  int mode=0
) as int, at @messagebox
'
'TEST
messagebox
a=messagebox text="helo", mode=1
print a
« Last Edit: March 11, 2018, 10:06:03 AM by Charles Pegge »

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 3719
    • Oxygen Basic
Re: Late binding to DLL / Attaching prototypes
« Reply #16 on: March 11, 2018, 09:59:02 AM »
The return type may also be placed at the start, C-style. In this case, declare/! is omitted.

int messagebox( ...

Code: [Select]
'2018-03-11 T 17:55:05
'c-style prototype overlay
uses corewin
'Create protype with default values for MessageBox
int messagebox(
  sys hwnd=0,
  char*text="",
  char*title="OxygenBasic",
  int mode=0
) at @messagebox
'
'TEST
messagebox
a=messagebox text="helo", mode=2
print a
« Last Edit: March 11, 2018, 10:06:43 AM by Charles Pegge »

Mike Lobanovsky

  • Admin Support Member
  • *****
  • Posts: 1854
Re: Late binding to DLL / Unprototyped Windows Headers
« Reply #17 on: March 11, 2018, 08:59:34 PM »
I beg your pardon?

Do you mean to say we're in for yet another set of incompatible headers to worry about before we're able to yell our first hello into the world of computer programming?!

As with all similarly half-hearted design decisions, a few questions immediately spring to mind:
  • How do I go about my life-long habit to explicitly invoke APIs by their full names, e.g. MessageBoxA, rather than by fraternalized if not overly familiar unisex MessageBox abbreviation?
  • What do I do with @n endings in mangled DLLs?
  • Why am I supposed to underscore (or not) function names in C language DLLs?
(and most sarcastically)
  • What if I want to call a property or method in a C++ DLL? I know I can do it in FBSL and I can give a half dozen reasons why I might want to do just that.

I've submitted my reasons, and practical solutions, for doing away with declares altogether in my earlier messages in this thread.

Do not you deign to explain yourself, esteemed sir, as to why you preferred to dismiss them? I smell conspiracy in the air... ;)
« Last Edit: March 12, 2018, 07:58:09 AM by Mike Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, 2 x nVidia GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 3719
    • Oxygen Basic
Re: Late binding to DLL / Unprototyped Windows Headers
« Reply #18 on: March 11, 2018, 10:30:43 PM »
Hi Mike,

MessageBox without the 'A': a modest compromise for the sake of common usage. At least we still have access to MessageBoxW in the same program. What's not to like? :)

Interesting that you raise the subject of name mangling. I have just been finessing o2's means of handling it:

! "_fname@4"

This will import the mangled '_fname@4' within the quotes, and extract 'fname' as the internal reference for it.
« Last Edit: March 12, 2018, 01:26:04 AM by Charles Pegge »

Josť Roca

  • Jr. Member
  • **
  • Posts: 61
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #19 on: March 11, 2018, 11:00:50 PM »
IMO the default should be unicode. I don't understand why many people are still using the "A" functions with an OS like Windows, that is fully unicode. The "A" functions are wrappers that convert strings to unicode and then call the "W" functions. In my framework for FreeBasic I only use unicode.

Mike Lobanovsky

  • Admin Support Member
  • *****
  • Posts: 1854
Re: Late binding to DLL / Unprototyped Windows
« Reply #20 on: March 12, 2018, 04:24:12 AM »
Hi Charles,

Thank you for picking up the glove! :)

MessageBox without the 'A': a modest compromise for the sake of common usage.

This doesn't explain what I should do with my MessageBoxA???

Interesting that you raise the subject of name mangling.

Actually I was raising it for the second time in this thread!  ::)

This will import the mangled '_fname@4' within the quotes, and extract 'fname' as the internal reference for it.

I agree that can handle the underscore prefixes and mangled postfixes. But you still won't be able to avoid aliases that would map ??3@YAXPAX@Z horrors into a limited subset of characters allowable in an intelligent language's function name. (that mumbo-jumbo is actually a real export from msvcrt.dll) :P

Now my question is, if you still need a pling, function name and alias to describe a single entry point among the 2,500+ first-aid APIs that you could have automated the entire process of importing, then why bother at all? Let us all fall prone before Josť and plead him to write a set of rock solid classic BASIC headers for us that we'll keep overlooking to supply, as is only natural for human beings, when deploying or exchanging our code? :)

I don't understand why many people are still using the "A" functions ...

Hi Josť,

I will tell you why.
  • How many businesses that are still dependent on PB would ever need anything but ASCII in their programs, do you think?
  • How many Indians, Chinese or Japanese followers do you think Charles is ever going to have?
  • It is quite feasible (though arguably practical) to produce sterling Unicode programs in a 100% ANSI language. The last person to register on the FBSL forum was a guy from India, a native Malayalam. He never advanced past very basic examples from an obscure installation of FBSL v3.4 but I showed him it is not that difficult. Here is an example of the 100% ANSI FBSL engine running a 100% Unicode demo to display mixed Hindi and Malayalam messages under his localized MS Windows installation. (It is written in medieval v3.4 notation when FBSL was still using unprototyped declares -- wink-wink, Charles -- rather than automatic imports I'm advocating here. Still usable with minor corrections in modern FBSL v3.5 though)

    As you can see, apart from the notorious curly braces, the code is hardly discernible from its imaginary ANSI C counterpart or, as it happens, from FreeBASIC's so called "modern syntax". AnsiToWide("") stands for its C/C++ L"" (or TEXT("")) counterpart. A matching WideToAnsi(varname$$) (in PB notation) has no C/C++ equivalent:
Code: [Select]
//#AppType Console
#Option Strict

#DllDeclare Kernel32(GetModuleHandleW, LoadLibraryW)
#DllDeclare User32(RegisterClassExW, CreateWindowExW, LoadIconW, LoadCursorW, _
MessageBoxW, IsDialogMessageW, PeekMessageW, DispatchMessageW, DefWindowProcW, _
SendMessageW, PostMessageW, TranslateMessage, GetSystemMenu)
#DllDeclare Gdi32(CreateFontW)

// Window style constants
#Define ES_MULTILINE 4
#Define WS_OVERLAPPEDWINDOW &HCF0000
#Define WS_CLIPCHILDREN &H2000000
#Define WS_CLIPSIBLINGS &H4000000
#Define WS_HSCROLL &H100000
#Define WS_VSCROLL &H200000
#Define WS_VISIBLE &H10000000
#Define WS_CHILD &H40000000

// Window extended style constants
#Define WS_EX_NOPARENTNOTIFY 4
#Define WS_EX_WINDOWEDGE 256
#Define WS_EX_APPWINDOW &H40000

// Child control ID constants
#Define IDC_RICHEDIT &H1000
#Define IDC_BUTTON &H1001

// Global variables
Dim hindi = "{\rtf1\ansi\ansicpg1251\deff0\deflang1049{\fonttbl{\f0\fswiss\fcharset1 Mangal;}{\f1\fswiss Mangal;}}" & _
"{\colortbl ;\red192\green0\blue0;}\viewkind4\uc1\pard\qc\cf1\b\f0\fs20\u2330?\u2368?\u2344?\u2368? \u2360?\u2366?" & _
"\u2341?\u2367?\u2351?\u2379?\u2306? \u2325?\u2375? \u2346?\u2381?\u2352?\u2348?\u2354? \u2348?\u2343?\u2366?\u2312?\f1 !" & _
"\par\f0\u2346?\u2381?\u2352?\u2327?\u2340?\u2368? \u2310? \u2352?\u2361?\u2368? \u2361?\u2376?\f1 !\par}"
Dim malayalam = "{\rtf1\ansi\ansicpg1251\deff0\deflang1049{\fonttbl{\f0\fnil\fprq2\fcharset1 Akshar Unicode;}{\f1\fnil\fprq2 Akshar Unicode;}" & _
"{\f2\fnil\fprq2\fcharset0 Akshar Unicode;}}{\colortbl ;\red0\green35\blue255;}\viewkind4\uc1\pard\qc\cf1\f0\fs28\u3335?\u3368?\u3405?\u3364?" & _
"\u3405?\u3375?\u3451? \u3384?\u3350?\u3390?\u3349?\u3405?\u3349?\u3454? \u3378?\u3399?\u3349?\u3405?\u3349?\u3393?\u3379?\u3405?\u3379? \u3338?\" & _
"u3383?\u3405?\u3374?\u3379?\u3374?\u3390?\u3375? \u3334?\u3382?\u3330?\u3384?\u3349?\u3454?\f1 !\par\f0\u3370?\u3393?\u3376?\u3399?\u3390?" & _
"\u3351?\u3364?\u3391? \u3381?\u3376?\u3393?\u3368?\u3405?\u3368?\u3393?\f1 !\lang1033\f2\par}"
Dim font = CreateFontW(18, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0, AnsiToWide("Akshar Unicode"))
Dim library = LoadLibraryW(AnsiToWide("riched20.dll"))
Dim window = Unicode_Form("Vinod's Unicode Special")
Dim button = Unicode_Control("Button", window, "Click me...", IDC_BUTTON, 670, 710, 90, 30, WS_CHILD BOr WS_VISIBLE)
Dim edit = Unicode_Control("RichEdit20W", window, "", IDC_RICHEDIT, _
212, 370, 370, 125, WS_CHILD BOr WS_VISIBLE BOr WS_VSCROLL BOr WS_HSCROLL BOr ES_MULTILINE)


// ================== EXECUTION STARTS HERE ====================
Sub Main()
  MakeNonResizable(window) // for artistic reasons
  If STANDALONE Then
    Fbsl_Tile(window, Fbsl_LoadImage(APPEXEPATH & "\Smile.jpg"))
  Else
    Fbsl_Tile(window, Fbsl_LoadImage(Left(Command(1), InStrRev(Command, "\")) & "Smile.jpg"))
  End If
  Resize(window, 0, 0, 800, 800)
  Center(window): Show(window)
 
  Unicode_Main()
End Sub
// =================== EXECUTION ENDS HERE =====================


// - Equivalent to FBSL built-in ASCII Begin Events/End Events -
Function Unicode_Events(ByVal hwnd As Integer, ByVal msg As Integer, ByVal wparam As Integer, ByVal lparam As Integer) As Integer
  #Define IDCANCEL 2
  #Define WM_CLOSE 16
  #Define WM_COMMAND 273
 
  Select Case msg
    Case WM_COMMAND
      If wparam = IDCANCEL Then
        PostMessageW(window, WM_CLOSE, 0, 0)
      ElseIf wparam = IDC_BUTTON Then
        OnClick()
        Return 0
      End If
    Case WM_CLOSE
      ExitProgram(0)
  End Select
  Return DefWindowProcW(hwnd, msg, wparam, lparam)
End Function

Sub Unicode_Main()
  #Define CS_DBLCLKS 8
  #Define WM_QUIT 18
  #Define PM_REMOVE 1
 
  Type MESSAGE
    hWnd As Integer
    message As Integer
    wParam As Integer
    lParam As Integer
    dwTime As Integer
    ptX As Integer
    ptY As Integer
  End Type
 
  Dim msg As MESSAGE
 
  While 1
    PeekMessageW(@msg, 0, 0, 0, PM_REMOVE)
    If msg.message = WM_QUIT Then Exit While
    If Not IsDialogMessageW(window, @msg) Then
      TranslateMessage(@msg)
      DispatchMessageW(@msg)
    End If
  WEnd
End Sub
// -------------------------------------------------------------

// ---------------------- Event handlers -----------------------
Sub OnClick()
  #Define WM_SETTEXT 12
 
  SendMessageW(button, WM_SETTEXT, 0, AnsiToWide("Clicked!"))
  Edit_Append(edit, hindi)
  Edit_Append(edit, malayalam)
End Sub

// ---------------------- Window creation ----------------------
Function Unicode_Form(FormTitle As String, _
  X As Integer = 0, Y As Integer = 0, Width As Integer = 320, Height As Integer = 200, _
  hWndOwner As Integer = NULL) As Integer
 
  #Define IDI_APPLICATION 32512
  #Define IDC_ARROW 32512
  #Define COLOR_BTNFACE 15
 
  Type WNDCLASSEXW
    cbSize As Integer
    style As Integer
    lpfnWndProc As Integer
    cbClsExtra As Integer
    cbWndExtra As Integer
    hInstance As Integer
    hIcon As Integer
    hCursor As Integer
    hbrBackground As Integer
    lpszMenuName As Integer
    lpszClassName As Integer
    hIconSm As Integer
  End Type
 
  Dim wcx As WNDCLASSEXW, szClassName = AnsiToWide("_FBSL_UNICODE_")
 
  wcx.cbSize = LenB(wcx)
  wcx.style = CS_DBLCLKS
  wcx.lpfnWndProc = AddressOf Unicode_Events
  wcx.hInstance = GetModuleHandleW(NULL)
  wcx.hIcon = LoadIconW(GetModuleHandleW, 101)
  wcx.hCursor = LoadCursorW(NULL, IDC_ARROW)
  wcx.hbrBackground = COLOR_BTNFACE + 1
  wcx.lpszClassName = @szClassName
  If Not RegisterClassExW(@wcx) Then
    MessageBoxW(NULL, $AnsiToWide("Unable to register Unicode window class"), $AnsiToWide("Error" & Chr(0)), 0)
    ExitProgram(-1)
  End If
 
  Dim hwin = CreateWindowExW( _
    WS_EX_APPWINDOW BOr WS_EX_WINDOWEDGE, _
    szClassName, AnsiToWide(FormTitle & Chr(0)), _
    WS_OVERLAPPEDWINDOW BOr WS_CLIPSIBLINGS BOr WS_CLIPCHILDREN, _
    X, Y, Width, Height, _
    NULL, NULL, GetModuleHandleW, NULL)
  If Not hwin Then
    MessageBoxW(NULL, $AnsiToWide("Unable to create Unicode window"), $AnsiToWide("Error" & Chr(0)), 0)
    ExitProgram(-1)
  End If
 
  Return hwin
End Function

Function Unicode_Control(ClassName As String, hWndParent As Integer, Caption As String, hCtlID As Integer = 0, _
  X As Integer = 0, Y As Integer = 0, Width As Integer = 0, Height As Integer = 0, _
  Style As Integer = WS_CHILD BOr WS_VISIBLE, XStyle As Integer = 0) As Integer
 
  #Define WM_SETFONT 48
 
  Dim hctl = CreateWindowExW( _
    XStyle, _
    $AnsiToWide(ClassName & Chr(0)), $AnsiToWide(Caption & Chr(0)), _
    Style, _
    X, Y, Width, Height, _
    hWndParent, hCtlID, GetModuleHandleW(NULL), NULL)
  If Not hctl Then
    MessageBoxW(NULL, $AnsiToWide("Unable to create Unicode control"), $AnsiToWide("Error" & Chr(0)), 0)
    ExitProgram(-1)
  End If
  SendMessageW(hctl, WM_SETFONT, font, TRUE)
 
  Return hctl
End Function

// ------------------------- Utilities -------------------------
Sub MakeNonResizable(hwnd As Integer)
  #Define WS_MAXIMIZEBOX &H10000
  #Define WS_MINIMIZEBOX &H20000
  #Define SC_SIZE &HF000
  #Define SC_MINIMIZE &HF020
  #Define SC_MAXIMIZE &HF030
  #Define SC_RESTORE &HF120
  #Define MF_BYCOMMAND 0
 
  Style_Remove(hwnd, WS_MINIMIZEBOX BOr WS_MAXIMIZEBOX)
  DeleteMenu(GetSystemMenu(hwnd, FALSE), SC_SIZE, MF_BYCOMMAND)
  DeleteMenu(GetSystemMenu, SC_MINIMIZE, MF_BYCOMMAND)
  DeleteMenu(GetSystemMenu, SC_MAXIMIZE, MF_BYCOMMAND)
  DeleteMenu(GetSystemMenu, SC_RESTORE, MF_BYCOMMAND)
End Sub

Sub Edit_Append(who As Integer, what As String)
  #Define ST_SELECTION 2
  #Define EM_SETTEXTEX 1121
 
  Type SETTEXTEX
    flags As Integer
    codepage As Integer
  End Type
 
  Dim ste As SETTEXTEX: ste.flags = ST_SELECTION
 
  SendMessageW(who, EM_SETTEXTEX, @ste, what)
End Sub


(BTW Josť, I find it extremely difficult to handle diacritics on my standard primary US English/secondary Cyrillic keyboard. Every time I type your name, I have to walk an extra mile to your site and use copy-paste to spell it "politically" correctly. Can I have your kind permission to spell it henceforth as Jose rather than Josť in my, er, simplified Anglo-Saxon? :) )
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, 2 x nVidia GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 3719
    • Oxygen Basic
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #21 on: March 12, 2018, 05:57:12 AM »
Hi Mike,

I quite like the plings! At least they are an improvement on declare function, and pass through the compiler pronto.I might even be able to shorten the route further.

And yes, I have encountered those dreadfully mangled names in MSVCRT, they are clearly not intended for public use, so I am deftly applying /* ... */ to all 58 of them.

Updated CoreWin list:
Code: [Select]
uses Kernel  '1595
uses User    '985
uses Gdi     '945
uses Comctl  '118
uses Comdlg  '28
uses Oleaut  '409
uses Shell   '484
uses Msvcrt  '1429 -58

'5935 declarations



PS Does Alt (keypad)130 ť work for you?

jcfuller

  • Full Member
  • ***
  • Posts: 143
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #22 on: March 12, 2018, 06:02:53 AM »
Mike,
  I find it extremely easy to do ansi/unicode with the same bc9 source thanks to a coulple of bcx'ers who wrote a utility to do ansi->unicode. I do not do unicode file IO though.

Charles,
  that's what I use for ť
 
James



Josť Roca

  • Jr. Member
  • **
  • Posts: 61
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #23 on: March 12, 2018, 06:16:50 AM »
> Can I have your kind permission to spell it henceforth as Jose rather than Josť in my, er, simplified Anglo-Saxon? :) )

Of course. You can also use Josep, which is my name in Valencian, my mother language, or Pepe or Pep, that are popular familiar abbreviations.

Mike Lobanovsky

  • Admin Support Member
  • *****
  • Posts: 1854
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #24 on: March 12, 2018, 06:26:43 AM »
Quote
PS Does Alt (keypad)130 ť work for you?

Psst! I also have a bunch of French friends, and they have a ton of accents in their names, and they agreed to my omissions, and they'll all be after my head if they ever see me still using the numpad in someone else's name! :D

I know POTs by heart and I can read binary numbers but I'm finding it progressively more and more difficult to recollect my wife's phone number. Do you want me to learn by heart the entire Alt code table for at least courier.ttf? Then Aurel will also demand I use literal ć in his last name...  ::)

What about calling me Михаил for a change, guys? Hope you have the Cyrillic pack installed to be able to see what it looks like in reality? ;D


@Jose:

Thank you very much! Jose will do just fine for me, and let's leave Pep for your buddies and relatives. :)


[EDIT] As an afterthought, BTW are y'all aware there are a lot of compact cheap throw-away keyboards around without the numpad extension targeted for people to whom size matters or every buck counts? Also, typical QWERTY WASD PC game control is impractical on AZERTY layouts used in France, Germany, etc?
« Last Edit: March 12, 2018, 06:47:25 PM by Mike Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, 2 x nVidia GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Josť Roca

  • Jr. Member
  • **
  • Posts: 61
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #25 on: March 12, 2018, 07:06:11 AM »
Quote
How many businesses that are still dependent on PB would ever need anything but ASCII in their programs, do you think?

In fact, PB DDTers's are using unicode without realizing it. Since PB 10+, DDT dialogs are unicode aware.

Quote
How many Indians, Chinese or Japanese followers do you think Charles is ever going to have?

None, if you insist in using ascii instead of unicode. There are a couple of Chinese guys translating the documentation of my framework for FreeBasic to his language. There is also an Indian guy that has started to use it.

Using it with Paul Squire's WinFBE editor and my CWSTR class you can do something like:

Code: [Select]
#include once "Afx/CWStr.inc"

DIM cws AS CWSTR = "Дмитрий Дмитриевич Шостакович"

DIM f AS LONG = FREEFILE
OPEN "test.txt" FOR OUTPUT ENCODING "utf16" AS #f
PRINT #f, cws
CLOSE #f

That is WYSIWYG unicode programming as easy as using ascii.

Mike Lobanovsky

  • Admin Support Member
  • *****
  • Posts: 1854
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #26 on: March 12, 2018, 07:32:43 AM »
Since PB 10+, DDT dialogs are unicode aware.

(10+) - 1 = (9+) versions seems like a long way indeed before adding "final touches", doesn't it?

But frankly, I do acknowledge the importance of Unicode, and that's why I suggested Charles make his A/W-less aliases bitness-dependent while OxygenBasic is still in a relatively early phase of development. This will help automate, to a significant extent, platform independent code development and smoother transition from ANSI to Unicode practices.

Yet I'd rather O2 fully supports both A and W API name versions alongside their respective "unisex" aliases in both 32-bit and 64-bit environments. Let's leave the final choice of names in all its variety to the end user.
« Last Edit: March 12, 2018, 07:08:45 PM by Mike Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, 2 x nVidia GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)

Arnold

  • Hero Member
  • *****
  • Posts: 648
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #27 on: March 12, 2018, 08:35:38 AM »
I am afraid but it seems I cannot use unicode with OxygenBasic. I tried this little code:

Code: [Select]
use corewin

wstring russian = "Привет, Михаил"
wstring caption = "Nice to meet you"

MessageBoxW null, russian, caption ,0

If I save this as Ansi and run the code I will get this output in a MessageBox:

Nice to meet you
(6 question marks, 6 question marks)

If I save the code as UTF-16 LE, I cannot even run the code (ASM ERR Line 1)

Is there a special trick to run unicode with OxygenBasic? The only example I found is examples\WideStrings\ReadUnicode.o2bas

Roland
« Last Edit: March 12, 2018, 08:43:55 AM by Arnold »

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 3719
    • Oxygen Basic
Re: Late binding to DLL / Call DWORD equiv / (for Ray)
« Reply #28 on: March 12, 2018, 10:07:43 AM »
Hi Roland,

Are you using unicode source code? I have not designed for that yet. But you should be able to getfile a unicode text, and do things with it using wstrings.

Mike Lobanovsky

  • Admin Support Member
  • *****
  • Posts: 1854
Re: Late binding to DLL / Call DWORD equiv / (for Arnold)
« Reply #29 on: March 12, 2018, 05:27:37 PM »
Is there a special trick to run unicode with OxygenBasic?

You could probably use a hidden RichEdit20W and BOM-less UTF-8 to do the conversion for you but that would not be a "trick" but rather a "hack".

But thanks for trying to impress me anyway Roland, and howdy yourself! :)
« Last Edit: March 12, 2018, 05:49:12 PM by Mike Lobanovsky »
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, 2 x nVidia GTX 650Ti w/ 2GB VRAM, Windows 7 Ultimate Sp1)