Author Topic: Need help with win32 api function CreateDIBSection  (Read 131 times)

0 Members and 1 Guest are viewing this topic.

helloworld

  • Newbie
  • *
  • Posts: 14
Need help with win32 api function CreateDIBSection
« on: June 19, 2017, 03:47:46 AM »
This is the function I am writing about:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd183494(v=vs.85).aspx

I can set up the DIB and use GDI functions with it. But I cannot write to the bitmap bits directly - then the app crashes.
It works in C++ and the problem seems to be the transliteration of the pointer to the pointer to the bits. In C++ it works this way:

Code: [Select]
HBITMAP dibm;
int* bits;
dibm = CreateDIBSection(dc, (const BITMAPINFO*)&bitmapinfoheader, DIB_RGB_COLORS, (void**) &bits, NULL, 0);
// then I can write at x,y:
bits[y*SCANLINELEN+x]=RGB(r,g,b);

Now the Oxygen Basic code. When I write to x,y, app crashes. When I use GDI on the DIB, it works:

Code: [Select]
sys dibm;
int* bits;
dibm = CreateDIBSection(dc, @bitmapinfoheader, DIB_RGB_COLORS, @@bits, NULL, 0);
' when I write to x,y, app crashes:
bits[y*SCANLINELEN+x]=RGB(r,g,b);

Q: How to put the right value into the pointer variable?

Also:
When I import the BOOL GDIflush(void) function like so:
extern lib "gdi32.dll"
! gdiflush() as sys
end extern

and when I use it, OB just prints out "gdiflush" and exits :D

also $/examples/Asm64/HelloWorld64.o2bas does not build: linker finds "unidentified names", namely messagebox. [version=A43 12:29 22/05/2017]

.
« Last Edit: June 19, 2017, 04:14:46 AM by helloworld »

Charles Pegge

  • Author
  • *****
  • Posts: 3224
    • Oxygen Basic
Re: Need help with win32 api function CreateDIBSection
« Reply #1 on: June 19, 2017, 09:21:31 AM »
helloworld,


! GdiFlush() as sys 'requires precise capitalisation

What prototype, if any,  are you using for CreateDIBSection?
You could try byval @@bits

I see the HelloWorld64 problem and will try to rectify soonest.

helloworld

  • Newbie
  • *
  • Posts: 14
Re: Need help with win32 api function CreateDIBSection
« Reply #2 on: June 19, 2017, 10:36:11 AM »
What prototype, if any,  are you using for CreateDIBSection?
You could try byval @@bits
None. Anyway the compiler requires #long#long#long#long#long#long. Byval (in the call I assume) does not work.
And thanks, GdiFlush works now.

Aurel

  • Jr. Member
  • **
  • Posts: 97
Re: Need help with win32 api function CreateDIBSection
« Reply #3 on: June 19, 2017, 11:03:22 AM »
helloworld

do you can post whole example that we can see what is what
also bitmap DIB require that you must know what kind of bitmap is
4,8,16,32 ..right?  ..or not ?

Charles Pegge

  • Author
  • *****
  • Posts: 3224
    • Oxygen Basic
Re: Need help with win32 api function CreateDIBSection
« Reply #4 on: June 19, 2017, 11:17:43 AM »
You can check whether the function has returned a valid bits pointer:
print @bits

Charles Pegge

  • Author
  • *****
  • Posts: 3224
    • Oxygen Basic
Re: Need help with win32 api function CreateDIBSection
« Reply #5 on: June 19, 2017, 07:15:50 PM »
Are you using indexbase 0 ?
The default is indexbase 1, which would corrupt the preceding variable space when attempting to write to bits[0].

helloworld

  • Newbie
  • *
  • Posts: 14
Re: Need help with win32 api function CreateDIBSection
« Reply #6 on: June 20, 2017, 07:55:43 AM »
Are you using indexbase 0 ?
The default is indexbase 1, which would corrupt the preceding variable space when attempting to write to bits[0].
That has been it! Thank you.

@Aurel
Here the (working) code for reference:
Code: [Select]
includepath "$/inc/"
indexbase 0

#include "MinWin.inc"

#define SRCCOPY 0xCC0020
#define BLACKNESS 0x42
#define WHITENESS 0xFF0062
#define SCANLEN 1280

type BITMAPINFOHEADER
DWORD biSize
LONG  biWidth
LONG  biHeight
WORD  biPlanes
WORD  biBitCount
DWORD biCompression
DWORD biSizeImage
LONG  biXPelsPerMeter
LONG  biYPelsPerMeter
DWORD biClrUsed
DWORD biClrImportant
end type

dim bmih as BITMAPINFOHEADER, dc0 as sys, dc1 as sys, bits as integer ptr

extern lib "Gdi32.dll"
! CreateDIBSection
! GdiFlush
end extern

#lookahead ' for procedures
s=error() : if s then: print s : end : end if

dim cmdline as asciiz ptr, inst as sys
&cmdline=GetCommandLine
inst=GetModuleHandle 0

WinMain inst,0,cmdline,SW_NORMAL
end

Function WinMain(sys inst, prevInst, asciiz*cmdline, sys show) as sys

WndClass wc
MSG      wm

sys hwnd, wwd, wht, wtx, wty, tax

wc.style = CS_HREDRAW or CS_VREDRAW
wc.lpfnWndProc = @WndProc
wc.cbClsExtra =0
wc.cbWndExtra =0   
wc.hInstance =inst
wc.hIcon=LoadIcon 0, IDI_APPLICATION
wc.hCursor=LoadCursor 0,IDC_ARROW
wc.hbrBackground = GetStockObject WHITE_BRUSH
wc.lpszMenuName = null
wc.lpszClassName = strptr "dib"

RegisterClass (@wc)

Wwd = 640 : Wht = 400
Tax = GetSystemMetrics SM_CXSCREEN
Wtx = (Tax - Wwd) /2
Tax = GetSystemMetrics SM_CYSCREEN
Wty = (Tax - Wht) /2
hwnd = CreateWindowEx 0,wc.lpszClassName,"dib",WS_OVERLAPPEDWINDOW,Wtx,Wty,Wwd,Wht,0,0,inst,0

ShowWindow hwnd,SW_SHOW
UpdateWindow hwnd

sys ret
do while ret := GetMessage &wm, 0, 0, 0
if ret = -1 then
'show an error message
else
TranslateMessage &wm
DispatchMessage &wm
end if
wend
End Function

function WndProc (hWnd, wMsg, wParam, lparam) as sys callback
select wmsg
case WM_CREATE
dc0=GetDC(NULL)
dc1=CreateCompatibleDC(dc0)
bmih = {sizeof(BITMAPINFOHEADER), 1280, -1024, 1, 32, 0, 0, 0, 0, 0, 0}
dibm=CreateDIBSection(dc1, @bmih, 0, @@bits, NULL, 0)
if dc0==NULL or dc1==NULL or dibm==NULL then DestroyWindow(hwnd)
SelectObject(dc1,dibm)
ReleaseDC(hwnd,dc0)

case WM_DESTROY
deleteobject(dibm)
deleteobject(dc1)
PostQuitMessage 0

case WM_PAINT
paint hwnd,dc1

case WM_KEYDOWN
keydown hwnd,wparam,lparam

case else
function=DefWindowProc hWnd,wMsg,wParam,lParam
end select
end function

function paint(hwnd,dc1)
rect rc
paintstruct ps

getclientrect hwnd,&rc
dc=beginpaint hwnd,&ps
BitBlt dc1, 0,0, 640,400, NULL, 0, 0, WHITENESS
gdiflush

fillr(bits, 10,10,100,100,0xFF0000)

/*
for i=0 to 1280*10-1
bits[i]=0xFF
next
*/

BitBlt(dc, 0,0, rc.right-rc.left,rc.bottom-rc.top, dc1, 0, 0, SRCCOPY)
endpaint hwnd,&ps
end function

function keydown(hwnd,wparam,lparam)
if wparam==0x1B 'escape
sendmessage hwnd,WM_CLOSE,0,0
end if
end function

function fillr(bm as integer ptr, x as dword,y as dword,w as dword,h as dword,col as dword)
int* bits=@bm
pitch=(SCANLEN-w)*4
@bits+=(y*SCANLEN+x)*4
for i=0 to <h
for j=0 to <w
bits=col : @bits+=4
next
@bits+=pitch
next
end function
« Last Edit: June 20, 2017, 08:54:11 AM by helloworld »

helloworld

  • Newbie
  • *
  • Posts: 14
Re: Need help with win32 api function CreateDIBSection
« Reply #7 on: June 20, 2017, 09:58:33 AM »
OB does not do even minimal optimisation. So I wonder how to use the assembler? Fragment below does not work.
Btw, Oxide has severe issues:
It may "eat" characters: it may do stuff like open the "save" dialogue, start code etc, when coding and typing i.e. "s" or "e".
Do you really use it for coding?

Code: [Select]
function fillr(bm as integer ptr, x as dword,y as dword,w as dword,h as dword,col as dword)

int* bits
int pitch

/*
@bits=@bm
pitch=(SCANLEN-w)*4
@bits+=(y*SCANLEN+x)*4
for i=0 to <h
for j=0 to <w
bits=col
                        @bits+=4
next
@bits+=pitch
next
*/


mov eax,bm ; @bits=@bm
mov bits,eax

mov ecx,1280 ; pitch=(SCANLEN-w)*4
sub ecx,w
shl ecx,2
mov pitch,ecx

mov eax,1280 ; @bits+=(y*SCANLEN+x)*4
mul y
add eax,x
shl eax,2
add bits,eax

mov eax,col
mov edx,bits
._for1 ; for i=0 to <h
dec h
jz _exitfor1
mov ecx,w
._for2 ; for j=0 to <w
dec ecx
jz _exitfor2
mov [edx],eax ; bits=col
add edx,4 ; @bits+=4
jmp _for2
._exitfor2
add edx,pitch ; @bits+=pitch
jmp _for1
._exitfor1
._leave
xor eax,eax

end function

« Last Edit: June 20, 2017, 10:42:22 AM by helloworld »

Charles Pegge

  • Author
  • *****
  • Posts: 3224
    • Oxygen Basic
Re: Need help with win32 api function CreateDIBSection
« Reply #8 on: June 20, 2017, 02:40:47 PM »
I use Oxide for most of my code testing without the 's' and 'e' problems you describe.

But when the control key is held down, a second 's' or 'e' keypress will insert ascii 19 or ascii 5 into the text. Which is an occasional nuisance that needs to be fixed.


re: assembler

You can display the assembly code generated by any line of basic by inserting #show at the beginning of the line.

Optimisation is a work in progress, but the gains from hand-written asm are usually small, and maintaining 32-bit and 64-bit compatibility can be tricky.

To resolve the address of any variable, including pointered variables, use the pseudo-instruction addr

addr eax,bm

« Last Edit: June 20, 2017, 08:04:20 PM by Charles Pegge »

Charles Pegge

  • Author
  • *****
  • Posts: 3224
    • Oxygen Basic
Re: Need help with win32 api function CreateDIBSection
« Reply #9 on: June 20, 2017, 07:54:36 PM »

HelloWorld64 fix:

https://github.com/Charles-Pegge/OxygenBasic/blob/master/Oxygen.zip


And the attached Oxide should be free of any ctrl-s and Ctrl-e problems:
« Last Edit: June 20, 2017, 09:01:21 PM by Charles Pegge »

helloworld

  • Newbie
  • *
  • Posts: 14
Re: Need help with win32 api function CreateDIBSection
« Reply #10 on: June 20, 2017, 10:56:29 PM »
I use Oxide for most of my code testing without the 's' and 'e' problems you describe.
The problem may have been due to keyboard layout..
I.e., it arised when I type the open bracket "[" (to do so, on my keyboard I have to prefix "Alr Gr"-key a.k.a. the right-side "Alt"-key) followed by i.e. "e" (->execute) or "s" (->save).

And now is fixed. :)

Other issues:
-The -a option to co2.exe is quite useless, because the listing is normally longer than the display height. Output shoud happen to file instead.

-It seems that it is not possible to transfer pointers via asm (!): there is no equivalent to @pointer1=@pointer2 witout knowing the stack position of the pointers?

« Last Edit: June 21, 2017, 01:30:26 AM by helloworld »

Charles Pegge

  • Author
  • *****
  • Posts: 3224
    • Oxygen Basic
Re: Need help with win32 api function CreateDIBSection
« Reply #11 on: June 21, 2017, 01:30:45 AM »
Glad it worked for you :)


re co2:

You can output asm to text file:

co2 -a -m prog.o2bas > t.txt

re: transferring pointers in asm:

One crude solution is to embed the basic line into your asm.

push edi
@pointer1 = @pointer2
pop edi

but what I need to do is support @:  addr eax,@pointer1
then this will be possible:

addr edx,@pointer1
addr eax,pointer2
mov [ecx],eax

Another solution is to go C :o
I have not tested this in depth yet, but it certainly works for simple expressions.

#cpointer on
'pointer1=pointer2
mov eax,pointer2
mov pointer1,eax
#cpointer off


« Last Edit: June 21, 2017, 01:55:31 AM by Charles Pegge »

helloworld

  • Newbie
  • *
  • Posts: 14
Re: Need help with win32 api function CreateDIBSection
« Reply #12 on: June 21, 2017, 02:03:12 AM »
You can output asm to text file:
co2 -a -m prog.o2bas > t.txt

My bad. I tried the pipe, but missed out the -m option :D

Quote
re: transferring pointers in asm:

I found this works:

Code: [Select]
dim p1 as integer ptr
dim p2 as integer ptr
dim a as integer
a=99
@p1=@a
(
mov eax,@p1
mov @p2,eax
)
print p2

But this does not:

Code: [Select]
dim as integer ptr p1
dim as integer ptr p2
dim a as integer
a=99
@p1=@a
(
mov eax,@p1
mov @p2,eax
)
print p2

This also works:

Code: [Select]
int* p1
int* p2
int a
a=99
@p1=@a
(
mov eax,@p1
mov @p2,eax
)
print p2