Author Topic: Using API Headers  (Read 16246 times)

0 Members and 1 Guest are viewing this topic.

Offline Gary Beene

  • Jr. Member
  • **
  • Posts: 96
  • User-Rate: +3/-0
Using API Headers
« on: January 25, 2012, 03:42:55 AM »
Jose,

Have you written an introduction to your headers?  I have a copy of the Help file, but it's more of a reference document. 

For example, to use the headers, what #Include statement do I use. Is there a "top level" #Include that will then incorporate all of the other *.inc files?  Or do I have to individually select which of your include files to incorporate, based on the requirements of each app?

Have I missed where on your site I should read for such summary information?

If I put both your includes and those from PowerBASIC into the Options/Compiler section of PBEdit, does the order matter (assuming that the "top level" includes are different)?  Is there a specific action I must take to avoid mixing the two sets of include files?

I think I know the answers to some of the questions I've asked, but I seem to have missed where I could have read the answers myself.

Offline Gary Beene

  • Jr. Member
  • **
  • Posts: 96
  • User-Rate: +3/-0
Re: Using API Headers
« Reply #1 on: January 25, 2012, 04:16:17 AM »
Hi Jose,

Along the same line of questioning ...

On the assumption that "win32api.inc" is the top level include for your API headers, can I rename it "jose_win32api.inc" without affecting anything?

If so, then I can tell at a glance which set of includes my app expects.

And if I do that, and keep both paths in the PB IDE compiler paths section, will there be no chance of mixing files between the two sets?

Offline Paul Elliott

  • Full Member
  • ***
  • Posts: 164
  • User-Rate: +40/-32
Re: Using API Headers
« Reply #2 on: January 25, 2012, 07:02:31 PM »
Gary,

Why not make your own inc with that name and just include Jose's main include?
That way any updates will not change your file and you will always get the right include.


Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #3 on: January 25, 2012, 09:37:26 PM »
The main file to include is "windows.inc", but you ca also use "win32api.inc", which is a stub file that simply calls "windows.inc". "windows.inc" already includes the most often needed other includes. For the others, you need to add #include <something> manually. Of course, as suggested by Paul, you can create a stub file that begins with #include "windows.inc", followed with other files of you interest. Mind you, there are more than 1.800 files. If "windows.inc" included all of them, it will take forever to compile even the tiniest program. PB is quite fast, but parsing more than 70 MB... To know which file to add for a particular wrapper, the name of the include file is listed at the end of the page for the function of the help file. For the Windows API functions, it is listed in the MSD documentation. I use the same names, except mine have an .inc extension whereas the C++ headers use the .h extension.

Quote
On the assumption that "win32api.inc" is the top level include for your API headers, can I rename it "jose_win32api.inc" without affecting anything?

This particular one, yes, because it is simply an stub file and it is not included by any other file, but don't rename any of the others or you will get file not found errors.

Quote
If I put both your includes and those from PowerBASIC into the Options/Compiler section of PBEdit, does the order matter (assuming that the "top level" includes are different)?  Is there a specific action I must take to avoid mixing the two sets of include files?

They can't b mixed, or you will get conflicts.

BTW I'm working in version III of my headers in which I'm using the constant %USEPBDECL to allow people that has already code written using the PB headers for PB10 to compile them with my headers, if they need to use the additional functionality that they provide, by simply adding #DEFINE %USEPBDECL = 1 at the top of the program, before any #INCLUDEs.

For example:

Code: [Select]
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION URLDownloadToFileA LIB "UrlMon.dll" _
    ALIAS "URLDownloadToFileA" ( _
    BYVAL pCaller    AS DWORD, _
    szURL            AS ASCIIZ, _
    szFileName       AS ASCIIZ, _
    BYVAL dwReserved AS DWORD, _
    BYVAL lpfnCB     AS DWORD) AS LONG
#ELSE
DECLARE FUNCTION URLDownloadToFileA IMPORT "URLMON.DLL" ALIAS "URLDownloadToFileA" ( _
   BYVAL pCaller AS IUnknown _                          ' __in LPUNKNOWN pCaller
 , BYREF szURL AS ASCIIZ _                              ' __in LPCSTR szURL
 , BYREF szFileName AS ASCIIZ _                         ' __in LPCSTR szFileName
 , BYVAL dwReserved AS DWORD _                          ' __in DWORD dwReserved
 , BYVAL lpfnCB AS IBindStatusCallback _                ' __in LPBINDSTATUSCALLBACK lpfnCB
 ) AS LONG                                              ' HRESULT
#ENDIF

PB is using DWORD instead of IUnknown and IBindStatusCallback because his includes have not inerface declarations, although in this case they could have used IUnknown inestead of DWORD.

I'm trying to minimize differences as much as I can.

For example, I was using:

Code: [Select]
' // Size = 18 bytes
TYPE NAME_BUFFER BYTE
   name       AS STRING * %NCBNAMSZ   ' UCHAR   name[NCBNAMSZ]
   name_num   AS BYTE                 ' UCHAR   name_num
   name_flags AS BYTE                 ' UCHAR   name_flags
END TYPE

and PB uses:

Code: [Select]
' // Size = 18 bytes
TYPE NAME_BUFFER BYTE
   sname      AS STRING * %NCBNAMSZ   ' UCHAR   name[NCBNAMSZ]
   name_num   AS BYTE                 ' UCHAR   name_num
   name_flags AS BYTE                 ' UCHAR   name_flags
END TYPE

Now, I'm using:

Code: [Select]
UNION NAME_BUFFER_NAME_UNION BYTE
   name       AS STRING * %NCBNAMSZ   ' UCHAR   name[NCBNAMSZ]
   ' // For compatibility with PB includes
   sname      AS STRING * %NCBNAMSZ   ' UCHAR   name[NCBNAMSZ]
END UNION
' // Size = 18 bytes
TYPE NAME_BUFFER BYTE
   NAME_BUFFER_NAME_UNION
   name_num   AS BYTE                 ' UCHAR   name_num
   name_flags AS BYTE                 ' UCHAR   name_flags
END TYPE

which allows to use both name and sname.

Of course, there are many irreconciliable differences that could only be solved by agreeing in which one is the most convenient to use and being adopted by both sets of includes.

There is also the problem that a good number of structures declared in the PB files are not properly aligned. I have checked each and every one of the near 8.000 structures included in my headers with the results given by the Visual C++ compiler, and ajusted them accordingly. So I'm confident that almost all (there is always room for errors) are correct.

Comparing the two sets is also allowing me to correct some minor mistakes in my headers.
« Last Edit: January 25, 2012, 09:42:38 PM by José Roca »

Offline Gary Beene

  • Jr. Member
  • **
  • Posts: 96
  • User-Rate: +3/-0
Re: Using API Headers
« Reply #4 on: January 26, 2012, 05:51:24 AM »
Jose/Paul,
Thank you for the responses/suggestions.

I plan to go with renaming Jose's "win32api.inc" to "jose_win32api.inc".  I like avoiding having two files of the same name, and I like the visual clarification of which includes I'm using.  I can see, however, why Jose has the "win32api.inc" stub file - to prevent the need to change code when using different includes. In my case, I'm happy to have that constriction in order to clarify for myself which includes I used to develop/test the code.

But, I'm still not clear on this point:
Quote
They can't be mixed, or you will get conflicts.
Is putting the two paths into the PBEdit Options section the same as "mixing" them? 

I would think it should not, as long as none of the respective includes are complete and have no missing, reference includes.

But, I can see that the mixing could occur if the first path (say, PB) was missing an expected include file and PBEdit then went to the 2nd path (where Jose's includes were placed) and found an include of the same name but not compatible with the PB includes.

Does this correctly describe how "mixing" would occur if both paths are placed in the PBEdit settings?

If so, then the correct approach seems to be to place only 1 path in the PBEdit settings, and completely replace it if I want to use the other set of includes.

Is this correct?

Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #5 on: January 26, 2012, 07:44:48 AM »
Quote
I can see, however, why Jose has the "win32api.inc" stub file - to prevent the need to change code when using different includes. In my case, I'm happy to have that constriction in order to clarify for myself which includes I used to develop/test the code.

Yes, that is the purpose, but be aware that the PB includes also have a file called windows.inc, so there is no problem if you don't change it. However, using your own you can add additional include files of you interest. My headers have two main include files, windows.inc, that provides the main functionality for the classical windows api, and ole2.inc, that provides the main functionality to work with COM.

The wrappers for the common controls are in separated files, not in commctrl.inc, because they contain many hundreds of functions.

AnimateCtrl.inc (Animation control)
ButtonCtrl.inc (Button control)
ComboBoxCtrl.inc (ComboBox control)
ComboBoxExCtrl.inc (ComboBoxEx control)
DateTimeCtrl.inc (Date Time control)
EditCtrl.inc (Edit control)
HeaderCtrl.inc (Header control)
HotKeyCtrl.inc (Hot Key control)
IPAddressCtrl.inc (IP Address control)
ListBoxCtrl.inc (ListBox control)
ListViewCtrl.inc (ListView control)
MonthCalCtrl.inc (Month Calendar control)
PagerCtrl.inc (Pager control)
ProgressBarCtrl.inc (Progress Bar control)
RebarCtrl.inc (Rebar control)
RichEditCtrl.inc (Rich Edit control)
ScrollBarCtrl.inc (Scroll Bar control)
StaticCtrl.inc (Static control)
StatusbarCtrl.inc (Status Bar control)
SysLinkCtrl.inc (SysLink control)
TabCtrl.inc (Tab control)
TaskDialogCtrl.inc (Task Dialog control)
ToolbarCtrl.inc (Toolbar control)
TrackbarCtrl.inc (Track Bar control)
TreeViewCtrl.inc (TreeView control)
UpDownCtrl.inc (UpDown control)

So, you may need to use #INCLUDE a bit more often that with the PB includes, but in turn you get faster compile times, and the current users of my headers are always counting bytes and milliseconds.

There are other main files for different technologies, such ADO.INC, for ADO support, ODBC.INC, for ODBC support, OPENGL, for OpenGL support, WMI..inc, for WMI support, etc. There are also classes such CODBC to use ODBC as easily as ADO, with a dotted syntax and exception handling, CGDIPLUS.INC, to allow to use GDI+ with a syntax similar to the one used by C++ programmers, there are graphic and image controls, an OLE container, and much more.

Quote
If so, then the correct approach seems to be to place only 1 path in the PBEdit settings, and completely replace it if I want to use the other set of includes.

Is this correct?

Yes, it is. In the introduction of the the post that has the attachment with the includes, it says:

Quote
You must also be aware that these headers are not extensions to the ones provided with the compiler, but a full replacement. Therefore, you must not mix them with the PowerBASIC include files in any way, neither directly (via #INCLUDE), nor indirectly (via the include path in the IDE).

Unzip the attached file to a folder of your choice and replace the PB Include path in the PB Ide or the editor that you are using to that folder instead of C:\PBWin10\WinApi.

You can have more folders, e.g. MyIncludes, as long as they're compatible with my headers. I use one of these for my translations of the headers of third party libraries.

I have no problems changing it because in the CSED editor I added four text boxes for the include's paths, and can quickly switch between them choosing the option with the dropdow menu of one of the toolbar buttons. The editor also comes with many templates. These are compatible with the PB IDE and you only need to copy them in the bin folder of the PB editor to access them. Just don't overwrite three or four that have the same name, such Default.pbtpl.

I have already modified some 150 files to allow them to be used with existing code that uses the PB includes. It remains 50 of them and then the worst part: to test them with existing code. I will test with my hundreds of examples to check that I haven't broken anything in the process and then I will try the PB10 examples and some of the latest posts in the PB forum that use the PB 10 includes. The purpose is to allow PBer's to use my headers with his existing PB10 code without having to make changes, or at least as less as possible.
« Last Edit: January 27, 2012, 06:13:41 AM by José Roca »

Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #6 on: January 26, 2012, 08:15:03 AM »
This example demonstrates how to use the GDI+ raw api with a DDT graphic control.

Code: [Select]
' ########################################################################################
' Microsoft Windows
' File: EX_DDT_GDIP_DrawLine_02.bas
' Contents: GDI+ example
' This version uses a DDT graphic control
' Compilers: PBWIN 10+, PBCC 6+
' Headers: Windows API headers 2.0+
' Copyright (c) 2012 José Roca. Freeware. Use at your own risk.
' Portions Copyright (c) Microsoft Corporation. All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

' SED_PBWIN
#COMPILE EXE
#DIM ALL
#INCLUDE "GDIPLUS.INC"

%IDC_GRAPHIC = 101

' ========================================================================================
' The following example draws a line.
' ========================================================================================
SUB GDIP_DrawLine (BYVAL hdc AS DWORD)

   LOCAL hStatus AS LONG
   LOCAL pGraphics AS DWORD
   LOCAL pPen AS DWORD

   ' // Create a graphics object
   hStatus = GdipCreateFromHDC(hdc, pGraphics)
   ' // Create a Pen
   hStatus = GdipCreatePen1(GDIP_ARGB(255, 255, 0, 0), 1, %UnitPixel, pPen)
   ' // Draw the line
   GdipDrawLine pGraphics, pPen, 0, 0, 200, 100

   ' // Cleanup
   IF pPen THEN GdipDeletePen(pPen)
   IF pGraphics THEN GdipDeleteGraphics(pGraphics)

END SUB
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN

   LOCAL hr AS LONG
   LOCAL hDlg AS DWORD
   LOCAL hdc AS DWORD

   ' // Initialize GDI+
   LOCAL GdipToken AS DWORD
   GdipToken = GdiPlusInit

   ' // Create the dialog
   DIALOG NEW PIXELS, 0, "GdipDrawLine", , , 400, 250, %WS_SYSMENU TO hDlg

   ' // Add a graphic control
   CONTROL ADD GRAPHIC, hDlg, %IDC_GRAPHIC,"", 0, 0, 400, 250
   ' // Select the drawing target
   GRAPHIC ATTACH hDlg, %IDC_GRAPHIC
   ' // Set the foreground and background colors
   GRAPHIC COLOR %BLACK, %WHITE
   ' // Clear the entire selected graphic window
   GRAPHIC CLEAR
   ' // Retrieve the handle of the device context
   GRAPHIC GET DC TO hdc
   ' // Draw the graphics
   GDIP_DrawLine hdc

   ' // Display and activate the dialog
   DIALOG SHOW MODAL hDlg, CALL DlgProc

   ' // Shutdown GDI+
   GdiplusShutdown GdipToken

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main Dialog procedure
' ========================================================================================
CALLBACK FUNCTION DlgProc() AS LONG

   SELECT CASE CBMSG

      CASE %WM_COMMAND
         SELECT CASE CB.CTL
            ' ...
            ' ...
         END SELECT

   END SELECT

END FUNCTION
' ========================================================================================

And this one using a DDT control and the CGDIPLUS class. Look at the code in the SUB GDIP_DrawLine to see the syntax differences.

Code: [Select]
' ########################################################################################
' Microsoft Windows
' File: EX_DDT_CGDIP_DrawLine.bas
' Contents: GDI+ example
' This version uses a DDT graphic control
' Compilers: PBWIN 10+, PBCC 6+
' Headers: Windows API headers 2.0+
' Copyright (c) 2012 José Roca. Freeware. Use at your own risk.
' Portions Copyright (c) Microsoft Corporation. All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

' SED_PBWIN
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "CGdiPlus.inc"   ' // CGdiPlus class

%IDC_GRAPHIC = 101

' ========================================================================================
' The following example draws a line.
' ========================================================================================
SUB GDIP_DrawLine (BYVAL pGdip AS IGdiPlus, BYVAL hdc AS DWORD)

   LOCAL graphics AS IGdipGraphics
   graphics = pGdip.Graphics(hdc)

   ' // Create a Pen object
   LOCAL redPen AS IGdipPen
   redPen = pGdip.Pen(pGdip.Color(255, 255, 0, 0))

   ' // Draw the line
   graphics.DrawLine(redPen, 0, 0, 200, 100)

END SUB
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN

   LOCAL hr AS LONG
   LOCAL hDlg AS DWORD
   LOCAL hdc AS DWORD

   ' // Create the dialog
   DIALOG NEW PIXELS, 0, "GdipDrawLine", , , 400, 250, %WS_SYSMENU TO hDlg

   ' // Add a graphic control
   CONTROL ADD GRAPHIC, hDlg, %IDC_GRAPHIC,"", 0, 0, 400, 250
   ' // Select the drawing target
   GRAPHIC ATTACH hDlg, %IDC_GRAPHIC
   ' // Set the foreground and background colors
   GRAPHIC COLOR %BLACK, %WHITE
   ' // Clear the entire selected graphic window
   GRAPHIC CLEAR
   ' // Retrieve the handle of the device context
   GRAPHIC GET DC TO hdc

   ' // Create an instance of the GdiPlus class
   LOCAL pGdip AS IGdiPlus
   pGdip = NewGdiPlus
   ' // Draw the graphics
   GDIP_DrawLine pGdip, hdc

   ' // Display and activate the dialog
   DIALOG SHOW MODAL hDlg, CALL DlgProc

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main Dialog procedure
' ========================================================================================
CALLBACK FUNCTION DlgProc() AS LONG

   SELECT CASE CBMSG

      CASE %WM_COMMAND
         SELECT CASE CB.CTL
            ' ...
            ' ...
         END SELECT

   END SELECT

END FUNCTION
' ========================================================================================

Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #7 on: January 26, 2012, 08:21:33 AM »
This one uses the GDI+ raw api and pure SDK code:

Code: [Select]
#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Header files for imported files
#INCLUDE ONCE "GDIPLUS.INC"    ' // GDI+
#INCLUDE ONCE "GraphCtx.INC"   ' // Graphic control
#INCLUDE ONCE "AfxWin.inc"    ' // Window wrappers

%IDC_GRCTX = 101

' ========================================================================================
' The following sample code draws a line.
' Change it with your own code.
' ========================================================================================
SUB GDIP_DrawLine (BYVAL hdc AS DWORD)

   LOCAL hStatus AS LONG
   LOCAL pGraphics AS DWORD
   LOCAL pPen AS DWORD

   hStatus = GdipCreateFromHDC(hdc, pGraphics)

   ' // Create a Pen
   hStatus = GdipCreatePen1(GDIP_ARGB(255, 255, 0, 0), 1, %UnitPixel, pPen)

   ' // Draw the line
   GdipDrawLineI pGraphics, pPen, 0, 0, 200, 100

   ' // Cleanup
   IF pPen THEN GdipDeletePen(pPen)
   IF pGraphics THEN GdipDeleteGraphics(pGraphics)

END SUB
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   LOCAL hwndMain AS DWORD
   LOCAL wcex AS WNDCLASSEX
#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

   ' // Initialize GDI+
   LOCAL GdipToken AS DWORD
   GdipToken = GdiPlusInit

   ' // Register the window class
   szClassName        = "MyClassName"
   wcex.cbSize        = SIZEOF(wcex)
   wcex.style         = %CS_HREDRAW OR %CS_VREDRAW
   wcex.lpfnWndProc   = CODEPTR(WndProc)
   wcex.cbClsExtra    = 0
   wcex.cbWndExtra    = 0
   wcex.hInstance     = hInstance
   wcex.hCursor       = LoadCursor (%NULL, BYVAL %IDC_ARROW)
   wcex.hbrBackground = GetStockObject(%WHITE_BRUSH)
   wcex.lpszMenuName  = %NULL
   wcex.lpszClassName = VARPTR(szClassName)
   wcex.hIcon         = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' // Sample, if resource icon: LoadIcon(hInst, "APPICON")
   wcex.hIconSm       = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' // Remember to set small icon too..
   RegisterClassEx wcex

   ' // Window caption
   szCaption = "GdipDrawLine"

   ' Create a window using the registered class
   hwndMain = CreateWindowEx(%WS_EX_CONTROLPARENT, _           ' extended style
                             szClassName, _                    ' window class name
                             szCaption, _                      ' window caption
                             %WS_OVERLAPPEDWINDOW OR _
                             %WS_CLIPCHILDREN, _               ' window style
                             0, _                              ' initial x position
                             0, _                              ' initial y position
                             400, _                            ' initial x nSize
                             300, _                            ' initial y nSize
                             %NULL, _                          ' parent window handle
                             0, _                              ' window menu handle
                             hInstance, _                      ' program instance handle
                             BYVAL %NULL)                      ' creation parameters

   ' // Center the window
   AfxCenterWindow hwndMain

   ' // Initialize the graphic control
   InitGraphCtx

   ' // Get the size of the client area
   LOCAL rc AS RECT
   GetClientRect(hwndMain, rc)

   ' // Create an instance of the graphic control
   LOCAL hCtrl AS DWORD
   hCtrl = CreateWindowEx(0, "GRAPHCTX", "", %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP, _
           rc.Left, rc.Top, rc.Right, rc.Bottom, hwndMain, %IDC_GRCTX, hInstance, BYVAL %NULL)

   ' // Get the memory device context of the graphic control
   LOCAL hdc AS DWORD
   hdc = GraphCtx_GetDc(hCtrl)

   ' // Draw the graphics
   GDIP_DrawLine hdc

   

   ' // Show the window
   ShowWindow hwndMain, nCmdShow
   UpdateWindow hwndMain

   ' // Message handler loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      IF IsDialogMessage(hwndMain, uMsg) = 0 THEN
         TranslateMessage uMsg
         DispatchMessage uMsg
      END IF
   WEND

   ' // Shutdown GDI+
   GdiplusShutdown GdipToken

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   LOCAL hCtrl AS DWORD
   LOCAL hDC AS DWORD

   SELECT CASE wMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)
            CASE %IDCANCEL
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE %WM_DESTROY
         ' // Close the main window
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   FUNCTION = DefWindowProc(hwnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

And this one the GDI+ raw api and my CWindow class:

Code: [Select]
' ########################################################################################
' Microsoft Windows
' File: CW_GraphCtrlGdipSkeleton.pbtpl
' Contents: Template - CWindow Graphic Control GDI+ Skeleton
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.03+
' Copyright (c) 2011 José Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Header files for imported files
%USEGRAPHCTX = 1
#INCLUDE ONCE "CWindow.inc"   ' // CWindow class

%IDC_GRCTX = 1001

' ========================================================================================
' The following sample code draws a line.
' Change it with your own code.
' ========================================================================================
SUB GDIP_DrawLine (BYVAL hdc AS DWORD)

   LOCAL hStatus AS LONG
   LOCAL pGraphics AS DWORD
   LOCAL pPen AS DWORD

   ' // Create a graphics object
   hStatus = GdipCreateFromHDC(hdc, pGraphics)
   ' // Create a Pen
   hStatus = GdipCreatePen1(GDIP_ARGB(255, 255, 0, 0), 1, %UnitPixel, pPen)
   ' // Draw the line
   GdipDrawLineI pGraphics, pPen, 0, 0, 200, 100

   ' // Cleanup
   IF pPen THEN GdipDeletePen(pPen)
   IF pGraphics THEN GdipDeleteGraphics(pGraphics)

END SUB
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
'   SetProcessDPIAware

   ' // Create an instance of the CWindow class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   pWindow.CreateWindow(%NULL, "CWindow Graphic Control GDI+ Skeleton", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Set the client size
   pWindow.SetClientSize 400, 250
   ' // Change the background color
   pWindow.Brush = %COLOR_WINDOW + 1
   ' // Center the window
   pWindow.CenterWindow

   ' // Add a GDI+ aware graphic control
   LOCAL hCtl AS DWORD
   hCtl = pWindow.AddGdipGraphCtx(pWindow.hwnd, %IDC_GRCTX, "", 0, 0, pWindow.ClientWidth, pWindow.ClientHeight)

   ' // Draw the graphics
   GDIP_DrawLine(GraphCtx_GetDc(hCtl))

   

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   SELECT CASE uMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)
            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
               END IF
         END SELECT

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #8 on: January 26, 2012, 08:29:49 AM »
Some comparisons:

SDK + my graphic control + raw api

Compile time:  0.7 seconds, at 17624400 lines/minute
15024 bytes compiled code, 4028 bytes RTLibrary,
64 bytes string literals, and 3200 bytes dgroup.
Executable stack size:  1048576 bytes.
Disk image: 24576 bytes   Memory image: 7292 bytes.

CWindow+ my graphic control + raw api

Compile time:  0.7 seconds, at 18674914 lines/minute
22784 bytes compiled code, 16312 bytes RTLibrary,
172 bytes string literals, and 3540 bytes dgroup.
Executable stack size:  1048576 bytes.
Disk image: 46080 bytes   Memory image: 20024 bytes.

DDT + graphic control + raw api

Compile time:  0.6 seconds, at 20045400 lines/minute
5712 bytes compiled code, 38956 bytes RTLibrary,
28 bytes string literals, and 2804 bytes dgroup.
Executable stack size:  1048576 bytes.
Disk image: 52224 bytes   Memory image: 41788 bytes.

Offline Theo Gottwald

  • Administrator
  • Hero Member
  • *****
  • Posts: 928
  • User-Rate: +30/-4
    • it-berater
Re: Using API Headers
« Reply #9 on: January 26, 2012, 10:58:42 AM »
Jose, comparing CWindows with DDT or "Plain SDK" is unfair, because CWindows has a lot more features. It's class bvy itself.
Actually (maybe until Phoenix 3?) there is no alternative to the CWindows Class if somebody wants to make DPI-aware GUI's.

I have myself made such a "renamed" Jose_WinAPI-Version (its also somewhere here in the forum).
That can not be done manually, because all files must be renamend, and also all references in all files.
I have done it using a script file that time.

However i have dropped that approach because any update will need to have a complete new set created.
I actually make the manual switch between those two.

And for new projects of course Jose's favourable Header files are those of my choise if i use any API's.

One day I'll need to go to spain and check how many people work there really behind the synonym "Jose".
Sometimes i think it must be ten or more ...  ;D
« Last Edit: January 26, 2012, 11:06:36 AM by Theo Gottwald »

Offline Paul Elliott

  • Full Member
  • ***
  • Posts: 164
  • User-Rate: +40/-32
Re: Using API Headers
« Reply #10 on: January 26, 2012, 01:22:09 PM »
Gary,

I would be inclined to go with creating your own include file with "jose" in front of the name
to let you know it is special. And have it include Jose's Win32api.inc. that way when you update
to a new version there will be no need to check if anything changed ( not very likely that it would ).

Just 1 level of indirection and totally under your control. If you want/need to add INC files to it then
it only needs to be done once.


Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #11 on: January 27, 2012, 07:37:39 AM »
Quote
Jose, comparing CWindows with DDT or "Plain SDK" is unfair, because CWindows has a lot more features. It's class bvy itself.

I'm just showing the facts. Pure SDK is harder to use but produces faster and smaller executables. CWindow and the additional wrappers makes GUI progamming much easier, and about 12 KB of overhead is a little price to pay. This is noticeable with little examples, but not with big programs. Does it matter much if a program compiles to 712 KB instead of 700 KB? We are not talking here about 1.5 MB Hello Worlds. I did not release classes for PB9 because they added a lot of bloat, and for the wrapper functions I had to use also macros and %USEMACROS for the same reason. This has changed with the dead code removal of PB10 and now I can extend the language as much as I wish. DDT adds some more bloat, but this doesn't trouble me either. My main complain about it is that it can't be used in SDK GUI programming. I have chosen my way because when I need something not already available I only have to write it, instead of bothering Bob with endless wish lists and wait, and wait, maybe without luck. My suggestions to Bob are almost always about things that I can't do or that I can't do efficiently; things that Bob can do much better than I and that will run faster.

Anyway, CWindow is completely optional. You can use it, or use pure SDK, or DDT, or write your own class. You can even do GUI programming with the console compiler, which is of interest to some PBer's that don't own PBWIN but sometimes would like to use a GUI.

We must also consider that Bob is constrained by the fact that everything that he adds to the compiler has to work with all versions of Windows or many of his customers will complain. I have the freedom of writing things that can only work with the most recent versions of Windows. For example, my CVariant class adds some 180 methods to the already functionality built in the compiler. However, it needs at least Windows XP SP2, but if you don't need to support older OSEs, then it is a luxury to use to someone like me that uses COM and VARIANTs so often.



Offline Jim Dunn

  • Newbie
  • *
  • Posts: 36
  • User-Rate: +4/-0
Re: Using API Headers
« Reply #12 on: January 27, 2012, 04:12:15 PM »
José,

I was looking at your simple CWindow example (over in Patrice's thread) and wanted to know:

-- how would I code your CWindow example if I wanted
-- the user to be able to "stretch" the window, to make it bigger
-- but instead of all the boxes/buttons/text staying the same size, they get "bigger"
-- like stretching, or magnifying, so the user is able to read it more easily???

I hope I'm making this clear... some of my users have 27" monitors, and say my boxes/text/buttons are so small.

Thx!!

Online José Roca

  • Administrator
  • Hero Member
  • *****
  • Posts: 2483
  • User-Rate: +204/-0
Re: Using API Headers
« Reply #13 on: January 28, 2012, 08:54:08 AM »
You can ask the user for a magnification ratio and after

Code: [Select]
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

Use something like:

Code: [Select]
   pWindow.DPI = pWindow.DPI * 1.2

This will increase the size of the window and controls a 20%.

But only controls added with pWindow.AddXXX, not third party controls added with functions like CreateRRButton or other way.