Jose kindly provided an updated version of his basic SDK Template program at...
http://www.jose.it-berater.org/smfforum/index.php?topic=4072.0
...under his discussion of the use of his new includes updated for the new PowerBASIC compilers with their much awaited for wide character string capabilities. In that template he did this to handle the case of whether the app was to use ansi strings or wide character strings...
#IF %DEF(%UNICODE)
LOCAL szClassName AS WSTRINGZ * 80
LOCAL szCaption AS WSTRINGZ * 255
#ELSE
LOCAL szClassName AS ASCIIZ * 80
LOCAL szCaption AS ASCIIZ * 255
#ENDIF
It just occurred to me to see if the standard technique used in C/C++ to create ansi/wide character agnostic code would work in PowerBASIC, and it does seem to work as expected. For example, in C or C++, if the constant _UNICODE is defined, TCHAR is defined as an unsigned short int, that is, wchar_t. If _UNICODE isn't defined, TCHAR is simply a char, which in C/C++ is just an 8 bit quantity.
It seems we can do the same thing in PowerBASIC like so (%UNICODE not defined - so asci)...
'Console Compiler 6.0
#Compile Exe
#Dim All
#If %Def(%UNICODE)
Macro TCHAR = WStringz
#Else
Macro TCHAR = Asciiz
#EndIf
Function PBMain() As Long
Local szStr As TCHAR *16
szStr="Hello, World!"
Print "szStr = " szStr
Print "Sizeof(szStr) = " sizeof(szStr)
Print "Len(szStr) = " Len(szStr)
Waitkey$
PBMain=0
End Function
#If 0
Output
=============================
szStr = Hello, World!
Sizeof(szStr) = 16
Len(szStr) = 13
#EndIf
And if %UNICODE is defined, note sizeof(szStr) ends up as 32 instead of 16, but Len(szStr) is the same...
'Console Compiler 6.0
#Compile Exe
#Dim All
%UNICODE = 1
#If %Def(%UNICODE)
Macro TCHAR = WStringz
#Else
Macro TCHAR = Asciiz
#EndIf
Function PBMain() As Long
Local szStr As TCHAR *16
szStr="Hello, World!"
Print "szStr = " szStr
Print "Sizeof(szStr) = " sizeof(szStr)
Print "Len(szStr) = " Len(szStr)
Waitkey$
PBMain=0
End Function
#If 0
Output
=============================
szStr = Hello, World!
Sizeof(szStr) = 32
Len(szStr) = 13
#EndIf
And this works too in Jose's template. Here's my badly hacked up version of it showing the TCHAR thing...
#Compile Exe
#Dim All
%UNICODE = 1
#Include Once "windows.inc"
#If %Def(%UNICODE)
Macro TCHAR = WStringz
#Else
Macro TCHAR = Asciiz
#EndIf
Function WindowProc(Byval hwnd As Dword, Byval uMsg As Dword, Byval wParam As Dword, Byval lParam As Long) As Long
If uMsg=%WM_DESTROY Then
Call PostQuitMessage(0)
End If
Function = DefWindowProc(hwnd, uMsg, wParam, lParam)
End Function
Function WinMain(Byval hIns As Dword, Byval hPrev As Dword, Byval lpszCmdLine As Asciiz Ptr, Byval nCmdShow As Long) As Long
Local hMain As Dword
Local wcex As WNDCLASSEX
Local szClassName As TCHAR * 80
Local szCaption As TCHAR * 255
szClassName = "MyClassName"
wcex.cbSize = SIZEOF(wcex)
wcex.style = %CS_DBLCLKS OR %CS_HREDRAW OR %CS_VREDRAW
wcex.lpfnWndProc = CODEPTR(WindowProc)
wcex.cbClsExtra = 0
wcex.cbWndExtra = 0
wcex.hInstance = hIns
wcex.hCursor = LoadCursor (%NULL, Byval %IDC_ARROW)
wcex.hbrBackground = %COLOR_3DFACE + 1
wcex.lpszMenuName = %NULL
wcex.lpszClassName = VARPTR(szClassName)
wcex.hIcon = LoadIcon (%NULL, Byval %IDI_APPLICATION)
wcex.hIconSm = LoadIcon (%NULL, Byval %IDI_APPLICATION)
RegisterClassEx wcex
szCaption = "Generic SDK Program"
hMain=CreateWindowEx(%WS_EX_CONTROLPARENT,szClassName,szCaption,%WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN,350,50,400,350,%NULL,0,hIns,Byval %NULL) ' creation parameters
ShowWindow hMain, nCmdShow
UpdateWindow hMain
Local uMsg As tagMsg
While GetMessage(uMsg, %NULL, 0, 0)
TranslateMessage uMsg
DispatchMessage uMsg
Wend
Function = uMsg.wParam
End Function
I'm just presenting this as perhaps an alternate technique to putting #if %Def(UNICODE) around lots of variable declarations.
If have used it for demo purposes, but in fact I can't see any advantage of writing a program that can be compiled both as ansi or unicode. All my new code will use unicode, so I would not need #IF/#ENDIFs or TCHARs for string variables. My advice is to use WSTRINGs and WSTRINGZs and reserve STRINGs and ASCIIZs for when they are really needed, such calling third party DLLs that don't support unicode or when using a dynamic string as a buffer for bynary data. When calling the Windows API functions, in fact is advantegous to use WSTRINGZs strings and the "W" functions, because the "A" functions are wrappers that convert the string parameters to unicode and call the "W" function. The "A" functions still exist in the includes for compatibility with legacy code, and because many PBer's will need time to get used to unicode, but hope that they will disappear one day. They are wasting space and increasing compile time, and also so many MACROs can cause nesting overflow issues.
The problem I am having is that the main parts of my programs at work that I support are heavily database oriented, and display of the data in grids is rather central to the functionality of the GUI. For my Windows CE work I write my own grids, but for my desktop systems I stll use the SIGrid from Software Inovators, and it of course uses Ansi strings (from what I've gathered that control is in limbo No one has any luck contacting the company, and so I guess updates aren't likely). So there appears to be no way around conversions. I can use wide character strings in my ODBC database access, and of course wide character strings are used in COM (my apps interact with Excel a lot), but the SIGrid is the bottleneck at this point. I'd like to just go ahead and convert everything to wide, but unless I write my own grid or buy one I seem to be stuck.
The situation isn't too different with the 64 bit issue either. Just like we all knew wide character strings were here to stay, the same is true with 64 bit. I imagine the next version of PowerBASIC in two or three years will hit us with that. I'd like to get it all overwith - both the wide character string issue, and 64 bit. I was thinking of writing my own grid in C++ and that way I could kill both issues at once, i.e., wide strings and 64 bit. I need to think on it some.