Page 1 of 2
Small program - howto?
Posted: Wed Jul 14, 2004 12:04 pm
by thefool
Hi!
I have been playing a little with PB to get a very small file size.
I made a little editor (no saving/loading) just to test filesize.
it compiles to 14.0 kb and can be compressed with UPX to 7.0 kb. Compressed with FSG it gets down to 6.63 kb.
How to get it smaller? is there any way?
I got the example from Fasm Windows package, and wrote it in PB.
I dont want another compressor, but i want to have the compiled file size down. It is a very small size, but can it be any smaller?
here it is:
Code: Select all
mywin= OpenWindow(Win, 300, 191, 256, 256, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "MiniPad")
CreateGadgetList(mywin)
EditorGadget(edi, 0, 0, 256, 256)
CreateMenu(1,mywin)
MenuTitle("File")
MenuItem(1,"New")
MenuBar()
MenuItem(2,"Exit")
MenuTitle("Help")
MenuItem(3,"About")
Repeat
Select WaitWindowEvent()
Case #PB_Event_SizeWindow
ResizeGadget(edi,0,0,WindowWidth(),WindowHeight())
Case #PB_Event_CloseWindow
JMP l_a
Case #PB_Event_Menu
Select EventMenuID()
Case 1
SetGadgetText(edi,"")
Case 2
JMP l_a
Case 3
MessageBox_(mywin,"A small PB app","Minipad",MB_APPLMODAL )
EndSelect
EndSelect
Until Event = #PB_EventCloseWindow
a:
End
Notice im using the JMP command, so inline asm need to be on.
I dont know if goto and jmp has size differences.
Rules:
shall have 2 menu's. A "File" and a "Help"
The "File" shall have 3 items. "New", wich emptys the editor, a splitbar and a "exit" wich exits the program. The help menu shall have "About" wich displays a msgbox containing "Minipad" and "A small PB app". I chose to make it with API, because that cut a half KB off

The window shall be resizeable, and the editor shall be the same size as the form when resizing.
This is not asking other people to program for me. Take it as a little competition on who can make it smallest

Posted: Wed Jul 14, 2004 12:13 pm
by freak
Well, if you can rewrite the windows commands (openwindow, waitwindowevent,...)
with the Api, it will save you at least another 2kb in the uncompressed executable.
Timo
Posted: Wed Jul 14, 2004 12:17 pm
by thefool
Ok.
Im just playing with the size and that stuff.
Just so i know how to get programs smaller. I will go playing a little with api, maybe.
but, if i use an api instead openwindow can i still put gadgets on?
I havent tryed making windows with api before (only very little, but with c++).
Posted: Wed Jul 14, 2004 12:53 pm
by thefool
ok after a little fizzling with the win 32 api's for createwindow and createwindowEX i give up
Anyone can help me with an example or so?
Posted: Wed Jul 14, 2004 1:55 pm
by freak
Here is a little example.
You can put PB Gadgets on an API window but you will have to handle the
events yourself then.
It is very interesting, that with the new linker (PB 3.91), the difference
between the API code and the PB code is only 1Kb, whereas with the old
linker the difference was 2Kb.
Ok, here comes the API code:
Code: Select all
; events must be handled yourself in this callback, so we need the handles
; to all gadgets:
;
Global hButton, hText
Procedure MyCallback(Window, Message, wParam, lParam)
Select Message
Case #WM_CLOSE ; close button was pressed
PostQuitMessage_(0) ; this will cause the main loop to quit
Case #WM_COMMAND ; these are gadget events
If lParam = hButton ; compare lParam to the gadget handles to find out which
MessageRequester("","Pressed!")
EndIf
Case #WM_SIZE ; window size event
GetClientRect_(Window, @Rect.RECT)
If hText ; make sure the gadgt exists before using it!
SetGadgetText(0, "Size: "+Str(Rect\right)+"x"+Str(Rect\bottom))
EndIf
EndSelect
ProcedureReturn DefWindowProc_(Window, Message, wParam, lParam) ; do the default action. this is very important!
EndProcedure
; first, register a class
;
WindowClass.WNDCLASS
WindowClass\style = #CS_HREDRAW | #CS_VREDRAW
WindowClass\lpfnWndProc = @MyCallback()
WindowClass\hInstance = GetModuleHandle_(0)
WindowClass\hbrBackground = #COLOR_BTNFACE+1
WindowClass\lpszClassName = @"MyWindowClass"
If RegisterClass_(@WindowClass)
; now create the window
;
hWnd = CreateWindowEx_(#WS_EX_WINDOWEDGE, "MyWindowClass", "Window Title", #WS_SYSMENU | #WS_SIZEBOX | #WS_VISIBLE, 100, 100, 400, 400, #NULL, #NULL, GetModuleHandle_(0), #NULL)
If hWnd
; PB gadgets can be put on an API window
;
If CreateGadgetList(hWnd)
hText = TextGadget(0, 10, 10, 80, 20, "Size: 400x400")
hButton = ButtonGadget(1, 10, 40, 80, 20, "Press Me")
EndIf
; main loop. Events are handled in the callback
;
While GetMessage_(@msg.MSG, 0, 0, 0) > 0
TranslateMessage_(@msg)
DispatchMessage_(@msg)
Wend
EndIf
EndIf
End
And here is the same thing in PB:
Code: Select all
If OpenWindow(0, 100, 100, 400, 400, #PB_Window_SystemMenu|#PB_Window_SizeGadget, "Window Title")
If CreateGadgetList(WindowID())
TextGadget(0, 10, 10, 80, 20, "Size: 400x400")
ButtonGadget(1, 10, 40, 80, 20, "Press Me")
Repeat
Event = WaitWindowEvent()
If Event = #PB_EventGadget And EventGadgetID() = 1
MessageRequester("","Pressed!")
ElseIf Event = #PB_EventSizeWindow
SetGadgetText(0, "Size: "+Str(WindowWidth())+"x"+Str(WindowHeight()))
EndIf
Until Event = #PB_EventCloseWindow
EndIf
EndIf
End
You have to agree that the PB code is simply more sexy than the other one
Given the fact that you only gain 1kb in the uncompressed executable,
i would rather stick with the PB commands than take all the effort to use
API only.
Timo
Posted: Wed Jul 14, 2004 3:18 pm
by localmotion34
again i ask, why is an EXE being so small such a big deal. dont most computers have at least 512 megs of RAM nowadays? i have 1.5 gigs, so even an EXE that is 2 megs in size is a joke for this system. why do people care so much how tiny an EXE is?
Posted: Wed Jul 14, 2004 4:19 pm
by newbie
Hi,
I don't think it is about to "care" of teh file size, I think, at least for me, that it is an exciting challenge.
Where some people are excited to do a game, or a network capable programs, others extremely like (love) the challenge of always go further (and get tiny executables).
Don't tell me about the "go ASM so" argument, it's all about balance

Posted: Wed Jul 14, 2004 4:30 pm
by Codemonger
again i ask, why is an EXE being so small such a big deal. dont most computers have at least 512 megs of RAM nowadays? i have 1.5 gigs, so even an EXE that is 2 megs in size is a joke for this system. why do people care so much how tiny an EXE is?
I kinda agree, but i think program bloat might introduce things like memory fragmentation and stuff ... your prog ends up trying to manage memory with huge programs more than it spends processing your code. Smaller code sometimes produces faster code. Anyway i'm no expert i this area, but thats my opinion.
Posted: Wed Jul 14, 2004 4:34 pm
by thefool
localmotion34 wrote:again i ask, why is an EXE being so small such a big deal. dont most computers have at least 512 megs of RAM nowadays? i have 1.5 gigs, so even an EXE that is 2 megs in size is a joke for this system. why do people care so much how tiny an EXE is?
It's exciting to get small apps. And why i dont go asm is that i want to make small apps in PB. Its not how much ram it uses, its how big the size is on hdd. I am doing this for fun.
newbie is absolutely right about its not being about care, but its about fun.
Posted: Wed Jul 14, 2004 4:39 pm
by thefool
You have to agree that the PB code is simply more sexy than the other one
ok i agree

..
Posted: Wed Jul 14, 2004 5:38 pm
by NoahPhense
@Timo
good, im not the only one that thinks it's sexy..
- np
Posted: Wed Jul 14, 2004 5:55 pm
by El_Choni
This is even less sexy than Freak's API code, but saves 8 K more 8O
You could save a little more if by using a replacement for Str(), and maybe a little more by joining the resulting strings "manually":
Code: Select all
Global hText
#BS_VCENTER = $0c00
#BS_NOTIFY = $4000
#BS_CENTER = $300
Procedure WndProc(hWnd, uMsg, wParam, lParam)
result = 0
Select uMsg
Case #WM_CLOSE
PostQuitMessage_(0)
Case #WM_COMMAND
If wParam=5001
MessageBox_(0, "Pressed!", "", 0)
EndIf
Case #WM_CREATE
hText = CreateWindowEx_(0, "STATIC", "Size: 400x400", #WS_VISIBLE|#WS_CHILD|#SS_LEFT, 10, 10, 80, 20, hWnd, 5000, hInstance, 0)
hButton = CreateWindowEx_(0, "BUTTON", "Press Me", #WS_VISIBLE|#WS_CHILD|#BS_PUSHBUTTON|#BS_VCENTER|#BS_NOTIFY|#BS_CENTER, 10, 40, 80, 20, hWnd, 5001, hInstance, 0)
hFont = GetStockObject_(#DEFAULT_GUI_FONT)
SendMessage_(hText, #WM_SETFONT, hFont, 1)
SendMessage_(hButton, #WM_SETFONT, hFont, 1)
Case #WM_SIZE
GetClientRect_(hWnd, @rc.RECT)
If hText
SetWindowText_(hText, "Size: "+Str(rc\right)+"x"+Str(rc\bottom))
EndIf
EndSelect
ProcedureReturn DefWindowProc_(hWnd, uMsg, wParam, lParam)
EndProcedure
hInstance = GetModuleHandle_(0)
wc.WNDCLASSEX
wc\cbSize = SizeOf(WNDCLASSEX)
wc\style = #CS_HREDRAW|#CS_VREDRAW
wc\lpfnWndProc = @WndProc()
wc\hInstance = hInstance
wc\hbrBackground = #COLOR_BTNFACE+1
wc\lpszClassName = ?ClassName
wc\hCursor = LoadCursor_(#NULL, #IDC_ARROW)
InitCommonControls_()
If RegisterClassEx_(@wc)
hWnd = CreateWindowEx_(#WS_EX_WINDOWEDGE, ?ClassName, "Window Title", #WS_SYSMENU|#WS_SIZEBOX|#WS_VISIBLE, 100, 100, 400, 400, #NULL, #NULL, hInstance, #NULL)
If hWnd
ShowWindow_(hWnd, #SW_SHOW)
UpdateWindow_(hWnd)
While GetMessage_(@msg.MSG, 0, 0, 0) > 0
TranslateMessage_(@msg)
DispatchMessage_(@msg)
Wend
EndIf
EndIf
DataSection
ClassName:
Data.s "MyWindowClass"
EndDataSection
Posted: Wed Jul 14, 2004 6:59 pm
by thefool
Sweet. Compressed it with FSG to 2.6 kb
thats a small app. 8O
2.6 kb still having a window, 2 gadgets and gadgethandling!
Posted: Wed Jul 14, 2004 7:10 pm
by newbie
wow, good piece of code El_Choni !

..
Posted: Wed Jul 14, 2004 8:17 pm
by NoahPhense
thefool wrote:Sweet. Compressed it with FSG to 2.6 kb
thats a small app. 8O
2.6 kb still having a window, 2 gadgets and gadgethandling!
(masm with fsg)
could be even smaller... has a few controls in it..
test_size.exe 1.29kb
Controls.exe 1.70kb (this one is sweet)
ok last one..
(fasm with fsg) "we can't leave out fasm, as it is in PB"
DIALOG.EXE 1.35kb
- np