Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
translating win32API C tutorial to fB ::New question::
#1
Some time ago I decided to learn win32API
(or whatever the real name is) for C/C++ and I found a tutorial on the
net that seemed to be on my level.

(that I later gave up because of lack of amition is beside the point -coding apathy )

Now when fB came out I decided to give it a try again, but this time
translating the code in the examples to fB with the help from the
hello.bas win32API example coming with fB.

I have some problems/questions...

1) What is byval? and why do I pass numbers but not strings as byval?
2)why can't I put gszclassname as const in fB It complains about
wrong parameter type ar something like that. Is it about pointers to
string data and the stuff I've seen people have problems with in other threads?
3)Uh. Yeah, also: the code doesn't work (window creation failed) what am i doing wrong?

The C code
[syntax="c"]#include <windows.h>

const char g_szClassName[] = "myWindowClass";

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;

//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}

// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);

if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}[/syntax]

not working fB code...

[syntax="qbasic"]defint a-z
option explicit
option private

'$include once:'win\kernel32.bi'
'$include once:'win\user32.bi'
'$include once:'win\gdi32.bi'

declare function wndproc (byval hwnd as long, _
byval msg as long, _
byval wparam as long, _
byval lparam as long,) as integer

declare function WinMain(byval hinstance as long, _
byval hprevinstance as long, _
lpcmdline as string, _
byval nCmdShow as integer) as integer

end WinMain( GetModuleHandle(0), 0, Command$, SW_NORMAL )

function wndproc (byval hwnd as long, _
byval msg as long, _
byval wparam as long, _
byval lparam as long,) as integer
select case msg
case wm_close: destroywindow(hwnd)
case wm_destroy: postquitmessage 0
case else: wndproc=defwindowproc(hwnd,msg,wparam,lparam)
end select

wndproc=0
end function

function WinMain(byval hinstance as long, _
byval hprevInstance as long, _
lpcommandline as string, _
byval ncmdshow as integer) as integer
dim wc as wndclassex
dim hwnd as long
dim msg as msg
dim gszclassname as string
gszclassname="myWindowClass"
wc.cbsize=len(wndclassex)
wc.style=0
wc.lpfnwndproc=@wndproc
wc.cbclsextra=0
wc.cbwndextra=0
wc.hinstance=hinstance
wc.hicon=loadicon(0,IDI_APPLICATION)
wc.hcursor=loadcursor(0,IDC_ARROW)
wc.hbrbackground=GetStockObject( WHITE_BRUSH )
wc.lpszmenuname=0
wc.lpszclassname=strptr(gszclassname)
wc.hiconsm=loadicon(0,IDI_APPLICATION)

if registerclassex(wc)=0 then
messagebox 0,"window registration failed","error",MB_ICONEXCLAMATION or MB_OK
winmain=0
end 0
else
messagebox 0,"window registration sucsessful","woot",MB_ICONEXCLAMATION or MB_OK
end if

hwnd=createwindowex(WS_EX_CLIENTEDGE ,_
gszclassname ,_
"My window title" ,_
WS_OVERLAPPEDWINDOW ,_
CW_USEDEFAULT ,_
CW_USEDEFAULT ,_
240 ,_
120 ,_
0 ,_
0 ,_
hinstance ,_
0)
if hwnd=0 then
messagebox 0,"window creation failed","error",MB_ICONEXCLAMATION or MB_OK
winmain=0
end 0
end if

showwindow hwnd,ncmdshow
updatewindow hwnd
while getmessage(msg,0,0,0)>0
translatemessage(msg)
dispatchmessage(msg)
wend

winmain=msg.wparam
end function[/syntax] :-? :-? Sad
/post]
Reply
#2
Here is a tips from a newbie:

  1. Move
    Code:
    wndproc=0
    before the Select case in wndproc(..) function. If you delete the line, it still works though.
  2. Add CreateMenu() at 10th parameter for CreateWindowEx API call.
  3. Add brackets into
    Code:
    if ( hwnd = 0 ) then ...
    [/list:o]

    And here is the working code:
    [syntax="QBasic"]
    DEFINT a-z
    OPTION explicit
    OPTION private

    '$include once:'win\kernel32.bi'
    '$include once:'win\user32.bi'
    '$include once:'win\gdi32.bi'

    DECLARE FUNCTION wndproc (BYVAL hwnd AS LONG, _
    BYVAL msg AS LONG, _
    BYVAL wparam AS LONG, _
    BYVAL lparam AS LONG,) AS INTEGER

    DECLARE FUNCTION WinMain(BYVAL hinstance AS LONG, _
    BYVAL hprevinstance AS LONG, _
    lpcmdline AS STRING, _
    BYVAL nCmdShow AS INTEGER) AS INTEGER

    END WinMain( GetModuleHandle(0), 0, COMMAND$, SW_NORMAL )

    FUNCTION wndproc (BYVAL hwnd AS LONG, _
    BYVAL msg AS LONG, _
    BYVAL wparam AS LONG, _
    BYVAL lparam AS LONG,) AS INTEGER
    wndproc=0
    SELECT CASE msg
    CASE wm_close: destroywindow(hwnd)
    CASE wm_destroy: postquitmessage 0
    CASE ELSE: wndproc=defwindowproc(hwnd,msg,wparam,lparam)
    END SELECT

    END FUNCTION

    FUNCTION WinMain(BYVAL hinstance AS LONG, _
    BYVAL hprevInstance AS LONG, _
    lpcommandline AS STRING, _
    BYVAL ncmdshow AS INTEGER) AS INTEGER
    DIM wc AS wndclassex
    DIM hwnd AS LONG
    DIM msg AS msg
    DIM gszclassname AS STRING
    gszclassname="myWindowClass"

    wc.cbsize=LEN(wndclassex)
    wc.style=0
    wc.lpfnwndproc=@wndproc
    wc.cbclsextra=0
    wc.cbwndextra=0
    wc.hinstance=hinstance
    wc.hicon=loadicon(0,IDI_APPLICATION)
    wc.hcursor=loadcursor(0,IDC_ARROW)
    wc.hbrbackground=GetStockObject( WHITE_BRUSH )
    wc.lpszmenuname=0
    wc.lpszclassname=strptr(gszclassname)
    wc.hiconsm=loadicon(0,IDI_APPLICATION)

    IF registerclassex(wc)=0 THEN
    messagebox 0,"window registration failed","error",MB_ICONEXCLAMATION OR MB_OK
    winmain=0
    END 0
    ELSE
    messagebox 0,"window registration sucsessful","woot",MB_ICONEXCLAMATION OR MB_OK
    END IF

    hwnd=createwindowex(WS_EX_CLIENTEDGE ,_
    gszclassname ,_
    "My window title" ,_
    WS_OVERLAPPEDWINDOW ,_
    CW_USEDEFAULT ,_
    CW_USEDEFAULT ,_
    240 ,_
    120 ,_
    0 ,_
    CreateMenu() ,_
    hinstance ,_
    0)
    IF ( hwnd=0 ) THEN
    messagebox 0,"window creation failed","error",MB_ICONEXCLAMATION OR MB_OK
    winmain=0
    END 0
    END IF

    showwindow(hwnd,ncmdshow)
    updatewindow hwnd

    WHILE getmessage(msg,0,0,0)>0
    translatemessage(msg)
    dispatchmessage(msg)
    WEND

    winmain=msg.wparam
    END FUNCTION
    [/syntax]

    ps - this is kind of weird stuffs that need to completed when using wndclassex in basic compiler. probably, win32 experts can explain why... I am no expert btw...
= inc(¢) Big Grin
Reply
#3
Thanks!
It works now, although I didn't need to put brackets (right word?)
around hwnd=0

Do anyone know why these differences matter in fB compared to c?
/post]
Reply
#4
Probably because FB is not C, no matter how much some people want it to be.
I'd knock on wood, but my desk is particle board.
Reply
#5
:oops: I have total ignorance about the API and the only thing I managed to do so far is adding a simple button and a simple edit control into a window. Can someone give me an example of how I can read and later change the contents of the edit control by clicking the button??

Also why is only CreateWindowEx Function working and CreateWindow Function doesn’t work ?

Code:
DEFINT a-z
OPTION explicit
OPTION private

'$include once:'win\kernel32.bi'
'$include once:'win\user32.bi'
'$include once:'win\gdi32.bi'

    dim shared hInstance as long

DECLARE FUNCTION wndproc (BYVAL hwnd AS LONG,   _
                          BYVAL msg AS LONG,    _
                          BYVAL wparam AS LONG, _
                          BYVAL lparam AS LONG,) AS INTEGER

DECLARE FUNCTION WinMain(BYVAL hinstance AS LONG,     _
                         BYVAL hprevinstance AS LONG, _
                               lpcmdline AS STRING,   _
                         BYVAL nCmdShow AS INTEGER) AS INTEGER

END WinMain( GetModuleHandle(0), 0, COMMAND$, SW_NORMAL )

FUNCTION wndproc (BYVAL hwnd AS LONG,   _
                  BYVAL msg AS LONG,    _
                  BYVAL wparam AS LONG, _
                  BYVAL lparam AS LONG,) AS INTEGER
   wndproc=0
   SELECT CASE msg
   Case WM_CREATE
         DIM bclassname AS STRING
         DIM eclassname AS STRING
         bclassname="BUTTON"
         eclassname="EDIT"
         Dim hwndButton as long
         Dim hwndEdit as long
         hwndButton = createwindowex(WS_EX_LEFT,bclassname,"Hello",WS_VISIBLE or WS_CHILD or BS_DEFPUSHBUTTON,10,10,50,100,hwnd,null,hInstance,null)
         hwndEdit = createwindowex(WS_EX_DLGMODALFRAME,eclassname,"555",WS_CHILD or WS_VISIBLE or WS_VSCROLL or ES_LEFT or ES_MULTILINE or ES_AUTOVSCROLL,70,10,150,100,hwnd,null,hInstance,null)
         'SendMessage(hwndEdit, WM_SETTEXT, 0, lparam)
      CASE wm_close: destroywindow(hwnd)
      CASE wm_destroy: postquitmessage 0
      CASE ELSE: wndproc=defwindowproc(hwnd,msg,wparam,lparam)
   END SELECT

END FUNCTION

FUNCTION WinMain(BYVAL hinstance AS LONG,       _
                 BYVAL hprevInstance AS LONG,   _
                       lpcommandline AS STRING, _
                 BYVAL ncmdshow AS INTEGER) AS INTEGER
   DIM wc AS wndclassex
   DIM hwnd AS LONG
   DIM msg AS msg
   DIM gszclassname AS STRING
       gszclassname="myWindowClass"

   wc.cbsize=LEN(wndclassex)
   wc.style=0
   wc.lpfnwndproc=@wndproc
   wc.cbclsextra=0
   wc.cbwndextra=0
   wc.hinstance=hinstance
   wc.hicon=loadicon(0,IDI_APPLICATION)
   wc.hcursor=loadcursor(0,IDC_ARROW)
   wc.hbrbackground=GetStockObject( WHITE_BRUSH )
   wc.lpszmenuname=0
   wc.lpszclassname=strptr(gszclassname)
   wc.hiconsm=loadicon(0,IDI_APPLICATION)
  
   IF registerclassex(wc)=0 THEN
      messagebox 0,"window registration failed","error",MB_ICONEXCLAMATION OR MB_OK
      winmain=0
      END 0
   ELSE
      messagebox 0,"window registration sucsessful","woot",MB_ICONEXCLAMATION OR MB_OK    
   END IF
  
   hwnd=createwindowex(WS_EX_CLIENTEDGE    ,_
                       gszclassname        ,_
                       "My window title"   ,_
                       WS_OVERLAPPEDWINDOW ,_
                       CW_USEDEFAULT       ,_
                       CW_USEDEFAULT       ,_
                       300                 ,_
                       200                 ,_
                       0                   ,_
                       CreateMenu()        ,_
                       hinstance           ,_
                       0)
   IF ( hwnd=0 ) THEN
      messagebox 0,"window creation failed","error",MB_ICONEXCLAMATION OR MB_OK
      winmain=0
      END 0
   END IF
  
    
   showwindow(hwnd,ncmdshow)
   updatewindow hwnd

   WHILE getmessage(msg,0,0,0)>0
      translatemessage(msg)
      dispatchmessage(msg)
   WEND
  
   winmain=msg.wparam
END FUNCTION
Reply
#6
Quote:Thanks!
It works now, although I didn't need to put brackets (right word?)
around hwnd=0

Do anyone know why these differences matter in fB compared to c?

Hi:

I am another newbie using FreeBASIC for the first time, and but then FreeBASIC is new, so I guess we are all learning together.

I did not try your code, as zydon already got it working for you, but I will try answering your questions based on what I have see and read so far.

1)
A variable in FreeBASIC has a value and a memory address where that value is stored. If you send a variable to a Win API function BYVAL, you are sending its value. If you send a variable BYREF, you are sending the address. There is an exception to this simple rule. In C which all the windows API was written in, a string is an array of characters. In FreeBASIC it is a structure, containing the string of characters, the string length and the string type (and possibly some more info that I don’t recall). If a Windows API function expects the address of an array of characters, you can not send it the address of a BASIC string, or you will crash. Instead there is a convention that you send the string BYVAL, and the FreeBASIC compiler understands that what you actually want is to send a reference to the actual data inside the string.

2)
const char g_szClassName[] = "myWindowClass";

g_szClassName is a character pointer, not a constant like used in FreeBASIC. The prefix const is to tell the C++ compiler (and this is C++ code, not C code) not to allow the programmer to edit the string. Depending on how you tried to translate this into BASIC you might have mixed things up. A CONST in FreeBASIC behaves like a #define in C.

3)
wndproc=0

In FreeBASIC giving a value to the function return does not cause the function to exit. You need to add EXIT FUNCTION, or do as Zydon recommended, and move the wndproc=0 to before the select case. The problem with the original code was that

wndproc=defwindowproc(hwnd,msg,wparam,lparam)

just assigned a value to wndproc, but this value was never returned from the function because the function did not exit at that point. It was overwritten by wndproc=0 you had at the bottom of the function.

Have fun

Garvan
Reply
#7
Quote::

Can someone give me an example of how I can read and later change the contents of the edit control by clicking the button??

Also why is only CreateWindowEx Function working and CreateWindow Function doesn’t work ?

Hi:

The code below should help you on your way. Sorry about reformatting it, I have a habit of using all uppercase Keywords, and the code looked ugly with a mixture of different styles.

CreateWindowEx() is defined in the headerfiles, CreateWindow() is not.

In MinGW CreateWindow() is a macro that calls CreateWindowEx(). I used a similar macro in the code below just for testing.

Garvan


Code:
DEFINT a-z
OPTION explicit
OPTION PRIVATE

'$include once:'win\kernel32.bi'
'$include once:'win\user32.bi'
'$include once:'win\gdi32.bi'

CONST IDC_BUTTON1 = 2001

DIM SHARED hInstance AS long
DIM SHARED hwndButton AS long
DIM SHARED hwndEdit AS long

#DEFINE CreateWindow(a,b,c,d,e,f,g,h,i,j,k) CreateWindowEx(0,a,b,c,d,e,f,g,h,i,j,k)
                                                    
DECLARE FUNCTION wndproc (BYVAL hwnd AS LONG,   _
                          BYVAL msg AS LONG,    _
                          BYVAL wparam AS LONG, _
                          BYVAL lparam AS LONG,) AS INTEGER

DECLARE FUNCTION WinMain(BYVAL hinstance AS LONG,     _
                         BYVAL hprevinstance AS LONG, _
                         lpcmdline AS STRING,   _
                         BYVAL nCmdShow AS INTEGER) AS INTEGER



END WinMain( GetModuleHandle(0), 0, COMMAND$, SW_NORMAL )

FUNCTION wndproc (BYVAL hwnd AS LONG,   _
                  BYVAL msg AS LONG,    _
                  BYVAL wparam AS LONG, _
                  BYVAL lparam AS LONG,) AS INTEGER
  
  wndproc=0
  
  SELECT CASE msg
  CASE WM_COMMAND
    SELECT CASE LOWORD(wParam)
    CASE IDC_BUTTON1
      IF HIWORD(wParam) = BN_CLICKED THEN
        DIM fn AS STRING * 300  'Use a fixed length string bigger then the max size
        DIM text_len AS LONG
        text_len = GetWindowText(hwndEdit,fn, 256) 'request 256 characters max size
        IF text_len <> 0 THEN MessageBox 0,fn,"woot",MB_ICONEXCLAMATION OR MB_OK
      END IF
    END SELECT
          
  CASE WM_CREATE
    DIM bclassname AS STRING
    DIM eclassname AS STRING
    bclassname="BUTTON"
    eclassname="EDIT"
    hwndButton = createwindow(bclassname,"Hello",WS_VISIBLE OR WS_CHILD OR BS_DEFPUSHBUTTON,10,10,50,100,hwnd,IDC_BUTTON1,hInstance,null)
    hwndEdit = createwindow(eclassname,"555",WS_CHILD OR WS_VISIBLE OR WS_VSCROLL OR ES_LEFT OR ES_MULTILINE OR ES_AUTOVSCROLL,70,10,150,100,hwnd,null,hInstance,null)
        
    DIM s AS STRING
    s = "Some text"
    SendMessage(hwndEdit, WM_SETTEXT, 0, BYVAL s)
    'You can also use SetWindowText
    'SetWindowText(hwndEdit,s)
        
  CASE wm_close: destroywindow(hwnd)
  CASE wm_destroy: postquitmessage 0
  CASE ELSE: wndproc=defwindowproc(hwnd,msg,wparam,lparam)
  END SELECT

END FUNCTION

FUNCTION WinMain(BYVAL hinstance AS LONG,       _
                 BYVAL hprevInstance AS LONG,   _
                 lpcommandline AS STRING, _
                 BYVAL ncmdshow AS INTEGER) AS INTEGER
  
  DIM wc AS wndclassex
  DIM hwnd AS LONG
  DIM msg AS msg
  DIM gszclassname AS STRING
  gszclassname="myWindowClass"

  wc.cbsize=LEN(wndclassex)
  wc.style=0
  wc.lpfnwndproc=@wndproc
  wc.cbclsextra=0
  wc.cbwndextra=0
  wc.hinstance=hinstance
  wc.hicon=loadicon(0,IDI_APPLICATION)
  wc.hcursor=loadcursor(0,IDC_ARROW)
  wc.hbrbackground=GetStockObject( WHITE_BRUSH )
  wc.lpszmenuname=0
  wc.lpszclassname=STRPTR(gszclassname)
  wc.hiconsm=loadicon(0,IDI_APPLICATION)
    
  IF registerclassex(wc)=0 THEN
    messagebox 0,"window registration failed","error",MB_ICONEXCLAMATION OR MB_OK
    winmain=0
    END 0
  ELSE
    messagebox 0,"window registration sucsessful","woot",MB_ICONEXCLAMATION OR MB_OK
  END IF
    
  hwnd = createwindow(gszclassname        ,_
                      "My window title"   ,_
                      WS_OVERLAPPEDWINDOW ,_
                      CW_USEDEFAULT       ,_
                      CW_USEDEFAULT       ,_
                      300                 ,_
                      200                 ,_
                      0                   ,_
                      CreateMenu()        ,_
                      hinstance           ,_
                      0)
                    
  IF ( hwnd=0 ) THEN
    messagebox 0,"window creation failed","error",MB_ICONEXCLAMATION OR MB_OK
    winmain=0
    EXIT FUNCTION
  END IF
    
    
  showwindow(hwnd,ncmdshow)
  updatewindow hwnd

  WHILE getmessage(msg,0,0,0)>0
    translatemessage(msg)
    dispatchmessage(msg)
  WEND
    
  winmain=msg.wparam
END FUNCTION
Reply
#8
8) Thanks!!
Reply
#9
Yeah, CreateWindow is actually a macro in C, it isn't part of the Win API, only CreateWindowEx.

()'s used with compound statements only make them more clear, there's no difference in the generated code.
Reply
#10
isn't dialogbox() supported by fB? or is it also a macro?

[syntax="c"]int ret = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);[/syntax]

[syntax="qbasic"]dim ret as integer
ret=dialogbox(getmodulehandle(0), IDD_ABOUT, hwnd, aboutdialogproc)[/syntax]

The fB code gives me "error 42, Variable not declared, found 'dialogbox'"
Is dialogbox also just a macro? if so could someone point me to how I
should translate it to whatever I should translate it to.
/post]
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)