Small program - howto?

Everything else that doesn't fall into one of the other PB categories.
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Small program - howto?

Post 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 :)
Last edited by thefool on Wed Jul 14, 2004 1:00 pm, edited 1 time in total.
freak
PureBasic Team
PureBasic Team
Posts: 5948
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post 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
quidquid Latine dictum sit altum videtur
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post 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++).
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post 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?
freak
PureBasic Team
PureBasic Team
Posts: 5948
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post 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 :mrgreen:

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
quidquid Latine dictum sit altum videtur
localmotion34
Enthusiast
Enthusiast
Posts: 665
Joined: Fri Sep 12, 2003 10:40 pm
Location: Tallahassee, Florida

Post 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?

Code: Select all

!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post 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 ;)
- Registered PB user -

Using PB 4.00
Codemonger
Enthusiast
Enthusiast
Posts: 384
Joined: Sat May 24, 2003 8:02 pm
Location: Canada
Contact:

Post 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.
<br>"I deliver Justice, not Mercy"

    - Codemonger, 2004 A.D.
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post 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.
Last edited by thefool on Wed Jul 14, 2004 4:40 pm, edited 1 time in total.
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

You have to agree that the PB code is simply more sexy than the other one
ok i agree :D
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

..

Post by NoahPhense »

@Timo
good, im not the only one that thinks it's sexy.. ;)


- np
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post 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
El_Choni
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post 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!
newbie
Enthusiast
Enthusiast
Posts: 296
Joined: Tue Jul 29, 2003 5:47 pm
Location: FRANCE
Contact:

Post by newbie »

wow, good piece of code El_Choni ! :D
- Registered PB user -

Using PB 4.00
User avatar
NoahPhense
Addict
Addict
Posts: 1999
Joined: Thu Oct 16, 2003 8:30 pm
Location: North Florida

..

Post 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" :D

DIALOG.EXE 1.35kb

- np
Post Reply