• Welcome to Jose's Read Only Forum 2023.
 

Using The TCHAR Macro Technique From C/C++ With The New PowerBASIC Compilers

Started by Frederick J. Harris, April 16, 2011, 07:21:06 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frederick J. Harris

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.


José Roca

 
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.

Frederick J. Harris

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.