Hi,
I wonder if anyone knows how to create a DLL containing multiple images? I have just had a run-through with the sample DLL code, and it worked OK, but I don't know how to add images, and then retrieve them for use in an IWB program. Any ideas, anyone?
Brian
Brian,
Can you not have a resource file and add the images into it.
Then you could add / use LarryMc's "ExtractResource" in the dll?
https://www.ionicwind.com/forums/index.php?topic=5614.msg41457#msg41457
Maybe?
Andy.
OK, you say you can create a DLL.
set it up as a project with a .rc file
in the .rc file make an entry for each image that looks like this
201 BITMAP "\\img\\0001.bmp"
where 201 is a unique id number and
"\\img\\0001.bmp" is the name and path to the image.
export load_bitmap
Const IMAGE_BITMAP = 0
Declare import, LoadImageA(hinst:int, lpszName:pointer, uType:int, cxDesired:int, cyDesired:int, fuLoad:int),uint
sub load_bitmap(hint:int,imgno:int,w:int,h:int),uint
string bname
uint hBitmap2
hBitmap2=0
bname="#"+ltrim$(str$(imgno+200))
hBitmap2 = LoadImageA(hInt, bname, IMAGE_BITMAP, w,h, 0)
return hBitmap2
endsub
The above code should also be part of your dll.
This little adjustment is so that you can start calling img #1 from your program with this number scheme.
====================================
as usual your dll would go in the same folder as your app
the following line goes at the top of your app
DECLARE "Shape2LM.dll",load_bitmap(hint:int,imgno:int,w:int,h:int),uint
then load the bitmap with a call
uint hBitmap2=load_bitmap(hint,1,w,h)
and that's the basics
Larry,
Excellent - that's just what I needed. Right, here we go!
Brian
Larry, I keep getting this. Followed your instructions implicitly
Compiling...
a window frame.iwb
No Errors
Linking...
IWBasic Linker v1.11 Copyright © 2011 Ionic Wind Software
Unresolved external __imp_load_bitmap
Error: C:\Users\Public\Documents\IWBasic\projects\Hairdressing\a window frame.o - Unresolved extern __imp_load_bitmap
Error(s) in linking C:\Users\Public\Documents\IWBasic\projects\Hairdressing\a window frame.exe
Brian
you do know that in order to compile any app that uses a call to any dll you have to create a linking library.
I assumed you did
From the main menu of the IDE select Tools/Create Import Library
When the dialog opens find the dll you created and open it.
It will create a .lib with the same name as your dll and put it in your libs folder.
Now try to compile your app.
Larry,
I confess I hadn't done that. It now compiles fine, but doesn't show anything. I really want my image values to start at 1000. My .rc lines start at "1000 BITMAP" etc. Don't see why it shouldn't work with those values
Brian
without seeing your actual code and how you are using the handle to the bitmap I can't offer and further suggestion as to why it isn't working for you.
as for the numbering, you're correct; 200 or 1000 it doesn't matter.
are you actually getting a handle returned when you call load_bitmap?
No. This line: UINT hBitmap2=load_bitmap(hint,1,50,50) returns a zero
Brian
These are my files that am compiling. Had to rename the .rc with an extension of .txt
I'm not seeing why it's not working.
This code came from my custom button library.
question: why did you want your images in a separate dll instead of in your app itself? Just curious.
also, instead of putting that long full path name in your rc file.
just make a sub folder off your source file folder called img
and then type your rc entries like this
Quote1000 BITMAP "img\\arrow.bmp"
1001 BITMAP "img\\button.bmp"
1002 BITMAP "img\\custom.bmp"
1003 BITMAP "img\\help.bmp"
1004 BITMAP "img\\inc.bmp"
1005 BITMAP "img\\incx.bmp"
1006 BITMAP "img\\zoomin.bmp"
1007 BITMAP "img\\zoominx.bmp"
1008 BITMAP "img\\zoomout.bmp"
1009 BITMAP "img\\zoomoutx.bmp"
1010 BITMAP "img\\ICexclamation.bmp"
1011 BITMAP "img\\ICinfo.bmp"
1012 BITMAP "img\\ICquestion.bmp"
1013 BITMAP "img\\ICstop.bmp"
QuoteThis line: UINT hBitmap2=load_bitmap(hint,1,50,50) returns a zero
Which hinstance are you using? If the resource is hosted in the dll you have to use the dll's hinstance.
getting the hint value is the line of code that is missing
Larry and Fasecero,
Thanks for your replies. I normally do embed my graphics into the exe, but there are so many in this program. I'm up to 500kb so far, and still more to add. And I am going to shorten the path name down when I have it figured out. It's certainly a good learning exercise, anyway!
Although, how do I get the hInt value?
Brian
DECLARE IMPORT, GetModuleHandle ALIAS GetModuleHandleA(lpModuleName AS POINTER),INT
sub load_bitmap(imgno:int,w:int,h:int),uint
string bname
uint hBitmap2
hBitmap2=0
bname="#"+ltrim$(str$(imgno+200))
hBitmap2 = LoadImageA(GetModuleHandle(0), bname, IMAGE_BITMAP, w,h, 0)
return hBitmap2
endsub
Didn't tested the code but it should work. I remember myself a long time ago asking this same question and I think Larry told me that there was a global variable holding this value but I couldn't find that post.
Nope - recompiled, made new lib file. Still hBitmap2 returning zero, and no image shown
Might just give up on it, but I would really know how to do it!
Brian
This was a tough one. GetModuleHandle() return the executable hinstance even when it is called from the dll, didn't know that. The code below assumes that there is a 1001 bitmap resource
Dll
EXPORT load_bitmap
CONST IMAGE_BITMAP = 0
Declare import, LoadImageA(hint:int, lpszName:pointer, uType:int, cxDesired:int, cyDesired:int, fuLoad:int),uint
DECLARE IMPORT, GetModuleHandle ALIAS GetModuleHandleA(lpModuleName AS POINTER),INT
DECLARE IMPORT, _GetLastError ALIAS GetLastError(),INT
SUB MAKEINTRESOURCE(n as WORD),POINTER
pointer pReturn = 0
_asm
lea eax,[ebp-4]
mov ebx,[ebp+8]
mov [eax],ebx
_endasm
RETURN pReturn
endsub
EXTERN _hinstance as uint
sub load_bitmap(imgno:int,w:int,h:int),uint
RETURN LoadImageA(_hinstance, MAKEINTRESOURCE(imgno), IMAGE_BITMAP, w,h, 0)
endsub
Test
$include "windowssdk.inc"
$use "cfImages.lib"
DECLARE "cfImages.dll",load_bitmap(imgno:int,w:int,h:int),uint
WINDOW win
INT hInt
UINT hBitmap2
OPENWINDOW win,0,0,800,600,@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW,0,"Window",&win_handler
hBitmap2=load_bitmap(1001,50,50)
setcaption win,str$(hBitmap2)
SHOWIMAGE win,hBitmap2,@IMGBITMAP,50,50,50,50
WAITUNTIL ISWINDOWCLOSED(win)
END
SUB win_handler(),INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW win
CASE @IDCLOSEWINDOW
CLOSEWINDOW win
ENDSELECT
RETURN 0
ENDSUB
After several changes I didn't realize that I posted an alternate DLL code. For simplicity, here's Larry's original dll with the only change required being changing the hinst
EXPORT load_bitmap
CONST IMAGE_BITMAP = 0
Declare import, LoadImageA(hint:int, lpszName:pointer, uType:int, cxDesired:int, cyDesired:int, fuLoad:int),uint
DECLARE IMPORT, GetModuleHandle ALIAS GetModuleHandleA(lpModuleName AS POINTER),INT
EXTERN _hinstance as uint
sub load_bitmap(imgno:int,w:int,h:int),uint
string bname
uint hBitmap2
hBitmap2=0
bname="#"+ltrim$(str$(imgno))
hBitmap2 = LoadImageA(_hinstance, bname, IMAGE_BITMAP, w,h, 0)
return hBitmap2
endsub
Fasecero,
So which one do I use? And why do we need the hash symbol? Will be trying later today
Brian
Edit: Fasecero, your first solution works! Thank you
Yeah, sorry for the confusion. You can use either of the two.
Fasecero,
Sorry to bother you again, but I have been messing trying to make a bitmap button from your code, but with no success so far
For simplicity, I've been using Load_PNG_FromFile. Any ideas?
Brian
I believe that SETBUTTONBITMAPS should work just fine
SETBUTTONBITMAPS w1,BUTTON_1,Load_PNG_FromFile(...),0,0
Otherwise can you upload an example so we can see what happens?
Well, as you can see, I didn't get very far
I can display the image, but as for making it a button . . .
Brian
Here are two different ways to create a button with an image. Unfortunately RGNFROMBITMAP requires a .bmp from file or resource (too bad it doesn't accept an HBITMAP), so I can only show you how to make square buttons.
$include "windowssdk.inc"
$include "cfImages.inc"
WINDOW win
UINT hCake
OPENWINDOW win,0,0,640,480,@MINBOX|@MAXBOX|@SIZE,0,"PNG as button",&win_handler
SETWINDOWCOLOR win,RGB(200,255,200)
hCake=Load_PNG_FromFile(GETSTARTPATH+"birthday cake.png",100,100,0xFFC8FFC8)
SHOWIMAGE win,hCake,@IMGBITMAP,270,50,100,100
' method #1
CONST BUTTON_1 = 1
CONTROL win,@RGNBUTTON,"",105,201,104,104,0x50000000,BUTTON_1
SETBUTTONBITMAPS win, BUTTON_1, hCake, hCake, hCake
' method #2
CONST BUTTON_2 = 2
CONTROL win,@SYSBUTTON,"",265,201,104,104,0x50000000,BUTTON_2
ButtonSetImage(win, BUTTON_2, hCake)
WAITUNTIL ISWINDOWCLOSED(win)
DELETEIMAGE hCake,@IMGBITMAP
END
SUB win_handler(),INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW win
CASE @IDCLOSEWINDOW
CLOSEWINDOW win
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_1
CASE& BUTTON_2
IF @NOTIFYCODE = 0
/*button clicked*/
SETCAPTION(win,"You have just clicked one button")
ENDIF
ENDSELECT
ENDSELECT
RETURN 0
ENDSUB
SUB ButtonSetImage(WINDOW w, INT id, INT image)
INT handle = GetDlgItem(w.hwnd, id)
LONG style = GetWindowLong(handle,GWL_STYLE)
style = style | BS_BITMAP
SetWindowLong(handle,GWL_STYLE,style)
_SendMessage(handle, BM_SETIMAGE, IMAGE_BITMAP, image)
_SendMessage(handle, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0)
ENDSUB
Fasecero,
That set me looking for a way to remove the border, and this was the best I could do. There is no border on the bottom right button, and only shows a frame when you press it. The frame disappears when you press another button. Many thanks,
Brian
missing $include "cfImages.inc"
Larry,
It's included on a previous post under this topic in zip file birthday.zip (186.73 kB)
Brian
If you do not want any edge use a static. The subclass is optional to change the cursor when the mouse is over the control.
$include "windowssdk.inc"
$INCLUDE "Commctrl.inc"
$include "cfImages.inc"
WINDOW win
UINT hCake
INT subclassID = 12345
OPENWINDOW win,0,0,640,480,@MINBOX|@MAXBOX|@SIZE,0,"PNG as button",&win_handler
SETWINDOWCOLOR win,RGB(200,255,200)
hCake=Load_PNG_FromFile(GETSTARTPATH+"birthday cake.png",100,100,0xFFC8FFC8)
SHOWIMAGE win,hCake,@IMGBITMAP,270,50,100,100
CONST STATIC_1=1
CONTROL win,@STATIC,"",265,201,104,104,0x50000000,STATIC_1
StaticSetImage(win,STATIC_1,hCake)
SetWindowSubclass(GetDlgItem(win.hwnd, STATIC_1), &subclassStaticProc, subclassID, 0)
WAITUNTIL ISWINDOWCLOSED(win)
DELETEIMAGE hCake,@IMGBITMAP
RemoveWindowSubclass(GetDlgItem(win.hwnd, STATIC_1), &subclassStaticProc, subclassID)
END
SUB win_handler(),INT
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW win
CASE @IDCLOSEWINDOW
CLOSEWINDOW win
CASE @IDCONTROL
SELECT @CONTROLID
CASE STATIC_1
IF @NOTIFYCODE = 0
SETCAPTION(win,"You have just clicked the static")
ENDIF
ENDSELECT
ENDSELECT
RETURN 0
ENDSUB
SUB subclassStaticProc(hWnd:INT,uMsg:INT,wParam:INT,lParam:INT,uIdSubclass:UINT_PTR,dwRefData:DWORD_PTR),INT
SELECT uMsg
CASE WM_SETCURSOR
WINDOW w
w.hwnd = hWnd
SETCURSOR(w, @CSCUSTOM, LoadCursor(NULL, IDC_HAND))
RETURN TRUE
ENDSELECT
RETURN DefSubclassProc(hWnd, uMsg, wParam, lParam)
ENDSUB
SUB StaticSetImage(WINDOW w,INT id,INT image)
INT handle=GetDlgItem(w.hWnd,id)
LONG style=GetWindowLong(handle,GWL_STYLE)
style=style|SS_BITMAP|SS_NOTIFY
SetWindowLong(handle,GWL_STYLE,style)
_SendMessage(handle,STM_SETIMAGE,IMAGE_BITMAP,image)
ENDSUB
Well, we are learning some stuff at the moment! Works well here, as does all your code
Many thanks,
Brian
Also, if we want to complicate things even more :) we can make an OWNERDRAW button that uses a different image for each state: normal, over, pressed.
$include "windowssdk.inc"
$INCLUDE "Commctrl.inc"
$include "cfImages.inc"
WINDOW win
UINT hCake,hCakeOver,hCakePressed
INT subclassID = 12345
INT isOverButton = 0
OPENWINDOW win,0,0,640,480,@MINBOX|@MAXBOX|@SIZE,0,"PNG as button",&win_handler
SETWINDOWCOLOR win,RGB(200,255,200)
hCake=Load_PNG_FromFile(GETSTARTPATH+"birthday cake normal.png",140,140,0xFFC8FFC8)
hCakeOver=Load_PNG_FromFile(GETSTARTPATH+"birthday cake over.png",140,140,0xFFC8FFC8)
hCakePressed=Load_PNG_FromFile(GETSTARTPATH+"birthday cake pressed.png",140,140,0xFFC8FFC8)
SHOWIMAGE win,hCake,@IMGBITMAP,270,50,140,140
' method #2
CONST BUTTON_1 = 1
CONTROL win,@SYSBUTTON,"",265,201,140,140,0x50000000,BUTTON_1
ButtonSetImages(win, BUTTON_1)
SetWindowSubclass(GetDlgItem(win.hwnd, BUTTON_1), &subclassButtonProc, subclassID, 0)
WAITUNTIL ISWINDOWCLOSED(win)
DELETEIMAGE hCake,@IMGBITMAP
DELETEIMAGE hCakeOver,@IMGBITMAP
DELETEIMAGE hCakePressed,@IMGBITMAP
RemoveWindowSubclass(GetDlgItem(win.hwnd, BUTTON_1), &subclassButtonProc, subclassID)
END
SUB win_handler(),INT
SELECT @MESSAGE
CASE WM_SETCURSOR
isOverButton = 0
RedrawWindow(GetDlgItem(win.hwnd, BUTTON_1), NULL, NULL, RDW_INVALIDATE)
CASE @IDCREATE
CENTERWINDOW win
CASE @IDCLOSEWINDOW
CLOSEWINDOW win
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_1
IF @NOTIFYCODE = 0
SETCAPTION(win,"You have just clicked the button")
ENDIF
ENDSELECT
ENDSELECT
RETURN 0
ENDSUB
SUB subclassButtonProc(hWnd:INT,uMsg:INT,wParam:INT,lParam:INT,uIdSubclass:UINT_PTR,dwRefData:DWORD_PTR),INT
SELECT uMsg
CASE WM_SETCURSOR
isOverButton = 1
RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE)
WINDOW w
w.hwnd = hWnd
SETCURSOR(w, @CSCUSTOM, LoadCursor(NULL, IDC_HAND))
RETURN TRUE
CASE WM_DRAWITEM
IF *<DRAWITEMSTRUCT>lParam.itemState & ODS_DEFAULT THEN
DrawButtonImage(*<DRAWITEMSTRUCT>lParam.hDC, hCake, 0, 0, *<DRAWITEMSTRUCT>lParam.rcItem.right, *<DRAWITEMSTRUCT>lParam.rcItem.bottom)
ELSEIF *<DRAWITEMSTRUCT>lParam.itemState & ODS_SELECTED THEN
DrawButtonImage(*<DRAWITEMSTRUCT>lParam.hDC, hCakePressed, 0, 0, *<DRAWITEMSTRUCT>lParam.rcItem.right, *<DRAWITEMSTRUCT>lParam.rcItem.bottom)
ELSEIF isOverButton THEN
DrawButtonImage(*<DRAWITEMSTRUCT>lParam.hDC, hCakeOver, 0, 0, *<DRAWITEMSTRUCT>lParam.rcItem.right, *<DRAWITEMSTRUCT>lParam.rcItem.bottom)
ELSE
DrawButtonImage(*<DRAWITEMSTRUCT>lParam.hDC, hCake, 0, 0, *<DRAWITEMSTRUCT>lParam.rcItem.right, *<DRAWITEMSTRUCT>lParam.rcItem.bottom)
ENDIF
ENDSELECT
RETURN DefSubclassProc(hWnd, uMsg, wParam, lParam)
ENDSUB
SUB ButtonSetImages(WINDOW w, INT id)
INT handle = GetDlgItem(w.hwnd, id)
LONG style = GetWindowLong(handle,GWL_STYLE)
style = WS_CHILD | WS_VISIBLE | BS_OWNERDRAW
SetWindowLong(handle,GWL_STYLE,style)
_SendMessage(handle, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0)
ENDSUB
SUB DrawButtonImage(INT hDC, UINT hbit, INT x, INT y, INT width, INT height) ' alpha: 1 to 255
HDC hdcMem = CreateCompatibleDC(hDC)
HBITMAP hbmOld = SelectObject(hdcMem, hbit)
BITMAP bm
GetObject(hbit, LEN(bm), &bm)
StretchBlt(hDC, x, y, width, height, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY)
SelectObject(hdcMem, hbmOld)
DeleteDC(hdcMem)
ENDSUB
And another one bites the dust! How did you do the "glow" effect? I used paint.net, which had the birthday cake as a shape, and then I added the colours, and saved it as a PNG. Very useful program, and there are a lot of plugins for it
Brian
I have a very old copy of photoshop (I think it's a version more than 10 years old that was given for free for a limited time by adobe). I also have an old embarcadero that was given for free also, but I never liked delphi so I never touched it. I have heard good things from Paint.net, also for GIMP as alternatives. I did a kick search and found this short video to make a glow in paint.net, maybe it can help, my advice watch the video without sound, the music is terrible: https://www.youtube.com/watch?v=BR6BxROSPDg
Fasecero,
I remember the Photoshop giveaways. In the UK, you could buy a magazine with a CD inside, containing the full version (7, I think), no limitations, private or business use. Got to be over 10 years ago, now. Although it wasn't easy to update them later
My money-conscious MD asked me to take some money out of the petty cash, and go and buy 10 copies. I think we cleaned the town centre shops out!
I tried GIMP a few years ago, and found it very slow. I have the latest version now, and it has speeded up tremendously, although I don't think it is very friendly. Maybe I don't use it enough to give it a fair comment
Brian
There was a magazine with a CD-ROM many years ago â€" so long ago I don't remember the name, it was cheap and was filled with lots of shareware and freeware programs. At that time I still didn't have internet at home so I spent hours installing apps. In there I found out by pure chance a program called darkbasic that was able to make games, so I began to program. I was very bad at making games lol so I start to ask myself how traditional programs were made. Can't remember what I wrote in google but Creative Basic was the first result I got. MSDN guided me to study some c, but I only feel comfortable writting code with our tools in here :) Anyway sorry to get off track. I'm now interested in making a button with a glow effect, I mean with a transition or animation, no idea what it takes so we'll see
There are some plugins for paint.net which includes a button maker - it's pretty good and easy. So easy, even I made one!
https://forums.getpaint.net/topic/7186-madjik-all-plugins-last-updated-2018-04-07/
Brian
Thanx for sharing this !
Found this site some time ago :
(http://cd.textfiles.com/)
Quote
Who knew that the companies looking for a quick buck through the late 1980's and early 1990's with "Shovelware" CDs would become the unwitting archivists of the BBS age? No one did, but here we are, looking back, muttering thanks to these souless con artists as we plunder the very data they themselves took from a time now past.
if you're looking for some oldies sharewares then, this is the place to go...