Announcement

Collapse
No announcement yet.

Small simple Example of WindowsLess Window....

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Small simple Example of WindowsLess Window....

    Could someone post an example of a small WindowLess window....

    Something Like:

    Code:
    #COMPILE EXE
    #DIM ALL
    
     FUNCTION PBMAIN () AS LONG
    
        MAKE_WINDOW_LESS_WINDOW()
    
     END FUNCTION
    
    '------------------------------------------------------------------------------
    
     FUNCTION MAKE_WINDOW_LESS_WINDOW()
    
    
     END FUNCTION
    
    '------------------------------------------------------------------------------
    
     CALLBACK FUNCTION WINDOW_LESS_CALLBACK()
    
        SELECT CASE AS LONG CB.MSG
    
            CASE %WM_INITDIALOG
              MSGBOX "%WM_INITDIALOG"
              SETTIMER(GL_hDlg,  %TIMER_1,  5000)
    
    
    
            CASE %WM_TIMER
              KILLTIMER(GL_hDlg, %TIMER_1)
              MSGBOX "TIMES UP!"
    
              (HOW DO YOU KILL A PROGRAM THAT HAS NO DIALOG?)
    
        END SELECT
    
    
     END FUNCTION

  • #2
    You could create a Message-Only window to send / receive messages.
    Or for your example use SetTimer with a TimerProc. eg.
    Code:
    #DIM ALL
    #COMPILE EXE
    #IF %Def(%PB_CC32)
     #Break   On
     #Console Off
    #ENDIF
    #INCLUDE "WIN32API.INC"
    ' Following needed because of typo in WinUser.inc supplied with PBWin10, PBCC60
    DECLARE FUNCTION PostThreadMessage LIB "USER32.DLL" ALIAS "PostThreadMessageA" _
            (BYVAL idThread AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
    
    FUNCTION PBMAIN()
     LOCAL sTemp AS STRING
     LOCAL hThread, dwVar AS DWORD
      THREAD CREATE TimerThread(dwVar) TO hThread
      THREAD CLOSE hThread TO hThread : hThread = 0                 ' Release thread handle - not used here
    
     '  ? "Thread Started"
    
      Do: Sleep 50: Loop Until ThreadCount = 1                      ' Drop out of PBMain when Thread Function ends
    END FUNCTION
    '------------------/PBMain
    
    THREAD FUNCTION TimerThread(BYVAL dwVar AS DWORD) AS LONG
     STATIC TimerID AS DWORD
     LOCAL Msg      AS TAGMSG
        ' Start the timer
        TimerID = SetTimer(%NULL, %NULL, 1000, CODEPTR(TimerProc))  ' Post %WM_TIMER msg to TimerProc every 1000 msec
                                                                    ' Loop passes msg on to TimerProc until..
        WHILE GetMessage(Msg, %NULL, %NULL, %NULL) <> 0             ' %WM_QUIT causes  GetMessage to return '0' ~ end loop
          DispatchMessage Msg                                       ' DispatchMessage passes %WM_TIMER on to TimerProc.
        WEND
    
      KillTimer %NULL, TimerID                                      ' Kill the timer
      WinBeep 200,500
    END FUNCTION
    '------------------/TimerThread
    
    SUB TimerProc(BYVAL hWnd AS Dword, BYVAL uMsg AS Long, BYVAL TimerID AS Long, BYVAL dwTime AS DWORD)
      STATIC TimerCount AS LONG
      SELECT CASE uMsg
        CASE %WM_TIMER                                              ' Timer has 'fired'
          INCR TimerCount
          WinBeep 500,100
          IF TimerCount = 8 THEN                                    ' Bail out after n intervals
            PostThreadMessage (GetCurrentThreadID, %WM_QUIT, 0, 0)  ' Signal Quit to Msg Loop
          END IF
      END SELECT
    END SUB
    '------------------/TimerProc
    Rgds, Dave

    Comment


    • #3
      Why do you want a window at all?

      Maybe (almost certainly!) there is a way to do whatever you want to do without creating a window you don't want!

      Mr. Biggs has guessed you wanted to do some kind of timer application. I think that's a good guess....

      .. BUT..

      why are are making us guess at all?




      Michael Mattias
      Tal Systems Inc.
      Racine WI USA
      mmattias@talsystems.com
      http://www.talsystems.com

      Comment


      • #4

        (HOW DO YOU KILL A PROGRAM THAT HAS NO DIALOG?)
        A program ends when WinMain runs out of code to execute ==>
        Code:
         FUNCTION PBMAIN()    
             CALL MAIN
        END FUNCTION
        "Main" here could create a window (or dialog) or not as desired but it still ends when WinMain(PBMAIN) runs out of stuff to do!

        MCM
        Michael Mattias
        Tal Systems Inc.
        Racine WI USA
        mmattias@talsystems.com
        http://www.talsystems.com

        Comment


        • #5
          Another way...

          Code:
           
          #COMPILE EXE '#Win 9.07#
          #DIM ALL
          #REGISTER NONE
          #INCLUDE "Win32Api.inc"
          #INCLUDE "CommCtrl.inc"
          #INCLUDE "IMM.inc"
          
          GLOBAL hDlg AS DWORD
          '_____________________________________________________________________________
          
          CALLBACK FUNCTION DlgProc
          
           SELECT CASE CBMSG
          
             CASE %WM_INITDIALOG
               STATIC nAtom            AS DWORD
               STATIC HotKeyRegistered AS LONG
               nAtom = GlobalAddAtom("SomeHotkey" + STR$(TIMER))  'Control-Alt-F10 hotkey to end application
               IF nAtom THEN HotKeyRegistered = RegisterHotKey(CBHNDL, nAtom, %MOD_ALT OR %MOD_CONTROL, %VK_F10)
          
               PostMessage(hDlg, %WM_APP, 0, 0)
          
             CASE %WM_APP
               ShowWindow(hDlg, %SW_HIDE) 'Hide application
          
             CASE %WM_HOTKEY 'Hot key pressed
               IF CBWPARAM = nAtom THEN WinBeep(1500, 100) : DIALOG END hDlg
          
             CASE %WM_DESTROY
               IF nAtom THEN 'Clean up
                 IF HotKeyRegistered THEN UnregisterHotKey(hDlg, nAtom)
                 GlobalDeleteAtom(nAtom)
               END IF
          
            END SELECT
          
          END FUNCTION
          '_____________________________________________________________________________
          
          FUNCTION PBMAIN()
          
           DIALOG NEW %HWND_DESKTOP, "AppName", 20000, 20000, 0, 0, %WS_CAPTION, 0 TO hDlg 'Put application off screen
           DIALOG SHOW MODAL hDlg CALL DlgProc
          
          END FUNCTION
          '_____________________________________________________________________________
          '

          Comment


          • #6
            Here is a working version of the pseudo code from #1
            - Uses a Message-Only WIndow..
            A message-only window enables you to send and receive messages. It is not visible, doesn't show on the TaskBar, has no z-order, cannot be enumerated, and does not receive broadcast messages.
            The window simply dispatches messages.
            Code:
             
            #COMPILE EXE
            #DIM ALL
            #INCLUDE "WIN32API.INC"
            
            %TIMER_1      = 101
            
            '------------------------------------------------------------------------------
            
             FUNCTION PBMAIN () AS LONG
            
                MAKE_WINDOW_LESS_WINDOW()
            
             END FUNCTION
            
            '------------------------------------------------------------------------------
            
             FUNCTION MAKE_WINDOW_LESS_WINDOW() AS LONG
               LOCAL hDlg AS DWORD
            
               DIALOG NEW %HWND_MESSAGE, "Message-Only", 0, 0, 0, 0 TO hDlg
            
               DIALOG SHOW MODAL hDlg, CALL WINDOW_LESS_CALLBACK
            
             END FUNCTION
            
            '------------------------------------------------------------------------------
            
             CALLBACK FUNCTION WINDOW_LESS_CALLBACK() AS LONG
            
                SELECT CASE AS LONG CB.MSG
            
                    CASE %WM_INITDIALOG
                      MSGBOX "%WM_INITDIALOG",,"Set 5 sec Timer"
                      SETTIMER(Cb.Hndl,  %TIMER_1,  5000)
            
                    CASE %WM_TIMER
                      KILLTIMER(Cb.Hndl, %TIMER_1)
                      MSGBOX "TIMES UP!"
            
                      ' (HOW DO YOU KILL A PROGRAM THAT HAS MsgOnly DIALOG?)
                      DIALOG END CB.Hndl, 0
            
                END SELECT
            
            
             END FUNCTION
            
            '------------------------------------------------------------------------------
            Rgds, Dave

            Comment


            • #7
              Purely academic question...
              I was thinking it would be something like this:


              Code:
               '------------------------------------------------------------------------------
                 FUNCTION MAKE_WINDOW_LESS_WINDOW()
              
                    Do While GetMessage(Msg, %NULL, 0, 0)
                     'PostQuitMessage() exits from loop
                     TranslateMessage Msg
                     DispatchMessage Msg
              
                 Loop
              
                 END FUNCTION
                '------------------------------------------------------------------------------

              I am trying to figure out how you get a message pump going and tell it what function is the callback function...
              Just like a window just without a window.

              I was sure I had seen this done -- I just cant remember what it is called so I an search for it.

              Comment


              • #8
                I think Dave Biggs is pointing at what I was thinking...

                Comment


                • #9
                  Or I could just DIALOG HIDE hDlg

                  Comment


                  • #10
                    Perhaps DIALOG HIDE hDlg is exactly what I should do... I can use that dialog for the splash screen then hide it.

                    Comment


                    • #11
                      You can make a splash screen Dialog / Window into a Message-Only Window on the fly by re-assigning it's Parent..
                      eg SetParent Cb.Hndl, %HWND_MESSAGE
                      Rgds, Dave

                      Comment


                      • #12
                        Code:
                         
                        #COMPILE EXE '#Win 9.07#
                        #DIM ALL
                        #REGISTER NONE
                        #INCLUDE "Win32Api.inc"
                        #INCLUDE "IMM.inc"
                        
                        %Timer = 101
                        '_____________________________________________________________________________
                        
                        FUNCTION TimerProc(BYVAL hWnd AS DWORD, BYVAL uMsg AS LONG, BYVAL idEvent AS LONG, BYVAL dwTime AS DWORD) AS LONG
                         STATIC Counter AS DWORD
                        
                         WinBeep(1500, 100)
                         INCR Counter
                         IF Counter > 13 THEN
                           Keybd_event(%VK_CONTROL, MapVirtualKey(%VK_CONTROL, 0), 0, 0)
                           Keybd_event(%VK_MENU, MapVirtualKey(%VK_MENU, 0), 0, 0)
                           Keybd_event(%VK_F10, MapVirtualKey(%VK_F10, 0), 0, 0)
                           Keybd_event(%VK_F10, MapVirtualKey(%VK_F10, 0), %KEYEVENTF_KEYUP, 0)
                           Keybd_event(%VK_MENU, MapVirtualKey(%VK_MENU, 0), %KEYEVENTF_KEYUP, 0)
                           Keybd_event(%VK_CONTROL, MapVirtualKey(%VK_CONTROL, 0), %KEYEVENTF_KEYUP, 0)
                         END IF
                        
                        END FUNCTION
                        '_____________________________________________________________________________
                        
                        FUNCTION PBMAIN()
                         LOCAL msg              AS TAGMSG
                         LOCAL hDlg             AS DWORD
                         LOCAL nAtom            AS DWORD
                         LOCAL HotKeyRegistered AS LONG
                        
                         DIALOG NEW %HWND_DESKTOP, "", 20000, 20000, 0, 0, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
                         DIALOG SHOW MODELESS hDlg
                        
                         nAtom = GlobalAddAtom("SomeHotkey" + STR$(TIMER))  'Control-Alt-F10 hotkey to end application
                         IF nAtom THEN HotKeyRegistered = RegisterHotKey(hDlg, nAtom, %MOD_ALT OR %MOD_CONTROL, %VK_F10)
                        
                         ShowWindow(hDlg, %SW_HIDE) 'Hide application
                        
                         SetTimer(hDlg, %Timer, 1000, CODEPTR(TimerProc))
                        
                         WHILE GetMessage(Msg, %NULL, 0, 0) > 0
                           IF IsDialogMessage(hDlg, Msg) THEN
                             IF msg.message = %WM_HOTKEY THEN EXIT 'Hot key pressed
                           'ELSE
                             'TranslateMessage(Msg)
                             'DispatchMessage(Msg)
                           END IF
                         WEND
                        
                         IF nAtom THEN 'Clean up
                           IF HotKeyRegistered THEN UnregisterHotKey(hDlg, nAtom)
                           GlobalDeleteAtom(nAtom)
                         END IF
                        
                         DIALOG END hDlg
                        
                         WinBeep(500, 100)
                        
                        END FUNCTION
                        '_____________________________________________________________________________
                        '

                        Comment


                        • #13
                          The PBCC echo server sample without stripping out the unneeded code.
                          Code:
                          #COMPILE EXE   'EchoServ.bas
                          #DIM ALL
                          #INCLUDE "win32api.inc"
                          %FD_READ                    = &B1
                          %FD_WRITE                   = &B10
                          %FD_ACCEPT                  = &B1000
                          %FD_CONNECT                 = &B10000
                          %FD_CLOSE                   = &B100000
                          %INVALID_SOCKET             = &HFFFFFFFF???
                          
                          %TCP_ACCEPT = %WM_USER + 4093  ' Any value larger than %WM_USER + 500
                          %TCP_ECHO   = %WM_USER + 4094  ' Any value larger than %WM_USER + 500
                          
                          '------------------------------------------------------------------------------
                          ' Global variables
                          '
                          GLOBAL hEcho    AS LONG
                          GLOBAL hServer  AS LONG
                          GLOBAL hwndTCP  AS LONG
                          GLOBAL hThread  AS LONG
                          
                          FUNCTION PBMAIN () AS LONG
                           THREAD CREATE WindowThread(%NULL) TO hThread
                           ? "Click to end the ECHO Server"
                           SendMessage hwndTCP, %WM_CLOSE, 0, 0
                          
                          END FUNCTION
                          
                          FUNCTION MakeWindow () AS LONG
                          
                              LOCAL wce         AS WndClassEx
                              LOCAL szClassName AS ASCIIZ * 64
                              LOCAL hWnd        AS LONG
                              LOCAL hInst       AS LONG
                          
                              STATIC registered AS LONG
                          
                              hInst = GetModuleHandle(BYVAL %NULL)
                          
                              IF ISFALSE registered THEN
                                  szClassName          = "PBTCPCOMM"
                                  wce.cbSize           = SIZEOF(wce)
                                  wce.style            = %CS_HREDRAW OR %CS_VREDRAW
                                  wce.lpfnWndProc      = CODEPTR(TcpProc)
                                  wce.cbClsExtra       = 0
                                  wce.cbWndExtra       = 0
                                  wce.hInstance        = hInst
                                  wce.hIcon            = %NULL
                                  wce.hCursor          = %NULL
                                  wce.hbrBackground    = %NULL
                                  wce.lpszMenuName     = %NULL
                                  wce.lpszClassName    = VARPTR(szClassName)
                                  wce.hIconSm          = %NULL
                                  RegisterClassEx wce
                                  registered = %TRUE
                              END IF
                          
                              hWnd = CreateWindow(szClassName, _
                                                  "TCP Handler", _
                                                  %WS_OVERLAPPEDWINDOW, _
                                                  5, 5, 10, 10, _
                                                  %NULL, _
                                                  %NULL, _
                                                  hInst, _
                                                  BYVAL %NULL)
                          
                              IF ISFALSE hWnd THEN
                                  hWnd = GetLastError
                              ELSE
                                  ShowWindow hWnd, %SW_HIDE
                                  UpdateWindow hWnd
                              END IF
                          
                              FUNCTION = hWnd
                          
                          END FUNCTION
                          '------------------------------------------------------------------------------
                          ' Callback function to handle events for the GUI window
                          '
                          FUNCTION TcpProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                                            BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
                          
                              STATIC hServer AS LONG
                              STATIC hEcho   AS LONG
                              LOCAL  sBuffer AS STRING
                              LOCAL  sPacket AS STRING
                          
                              SELECT CASE wMsg
                          
                              CASE %WM_CREATE
                                  hServer = FREEFILE
                                  TCP OPEN SERVER PORT 999 AS hServer TIMEOUT 5000
                                  IF ERR THEN
                                      sBuffer = "Couldn't create socket!"
                                  ELSE
                                      TCP NOTIFY hServer, ACCEPT TO hWnd AS %TCP_ACCEPT
                                      sBuffer = "Connected to Port 999"
                                  END IF
                                  LogEvent sBuffer
                                  hEcho = %INVALID_SOCKET
                                  FUNCTION = 1
                          
                              CASE %TCP_ACCEPT
                                  SELECT CASE LO(WORD, lParam)
                          
                                  CASE %FD_ACCEPT
                                      hEcho = FREEFILE
                                      TCP ACCEPT hServer AS hEcho
                                      TCP NOTIFY hEcho, RECV CLOSE TO hWnd AS %TCP_ECHO
                          
                                  END SELECT
                                  FUNCTION = 1
                          
                              CASE %TCP_ECHO
                                  SELECT CASE LO(WORD, lParam)
                          
                                  CASE %FD_READ
                                      IF hEcho <> %INVALID_SOCKET THEN
                                          ' Perform a receive-loop until there is no data left (ie, the end of stream)
                                          sBuffer = ""
                                          sPacket = ""
                                          DO
                                            TCP RECV hEcho, 1024, sBuffer
                                            sPacket = sPacket & sBuffer
                                          LOOP UNTIL sBuffer = "" OR ISTRUE EOF(hEcho) OR ISTRUE ERR
                          
                                          ' Send it back!
                                          IF LEN(sBuffer) THEN TCP SEND hEcho, sPacket & " -> Received Ok!"
                          
                                          LogEvent $DQ & sPacket & $DQ & " (" & FORMAT$(LEN(sPacket)) & " bytes)"
                                      ELSE
                                          LogEvent "* FD_READ Error!"
                                      END IF
                          
                                  CASE %FD_CLOSE
                                      TCP CLOSE hEcho
                                      hEcho = %INVALID_SOCKET
                          
                                  END SELECT
                                  FUNCTION = 1
                          
                              CASE %WM_DESTROY
                                  TCP CLOSE hServer
                          
                              END SELECT
                          
                              FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
                          
                          END FUNCTION
                          
                          '------------------------------------------------------------------------------
                          ' Event logging routine
                          '
                          SUB LogEvent (BYVAL Buffer AS STRING)
                          
                              Buffer = TIME$ & " - " & Buffer
                              ? Buffer
                          
                          END SUB
                          
                          '------------------------------------------------------------------------------
                          ' Spawn a thread to create/own the GUI window and run a thread message pump.
                          ' Each thread must operate it's own pump the GUI windows it owns.
                          '
                          THREAD FUNCTION WindowThread (BYVAL nIgnored AS LONG) AS LONG
                          
                              LOCAL Msg AS tagMsg
                          
                              hwndTCP = MakeWindow
                          
                              DO WHILE IsWindow(hwndTCP) AND GetMessage(Msg, %NULL, 0, 0)
                                  TranslateMessage Msg
                                  DispatchMessage Msg
                              LOOP
                          
                          END FUNCTION

                          Comment


                          • #14
                            If its an app that you have written and controlled the content, set it up to receive a HWND_BROADCAST message with WM_COMMAND so that when it receives that message, it closes down. Then an app you want to use to shut it down only has to send a message with the same handle and it will work just fine. You must create your own private message to do that.
                            hutch at movsd dot com
                            The MASM Forum

                            www.masm32.com

                            Comment


                            • #15
                              am trying to figure out how you get a message pump going and tell it what function is the callback function... Just like a window just without a window.
                              Just go back to the example you created for yourself when you took my advice and created one (1) application using SDK-style window creation and management. When you got that working, you must have started a message loop AND named a callback function ("window procedure") .

                              Didn't take that advice? Well, too bad. (I actually enjoy saying "I told you so.")

                              All that said, why do you want a message pump (message loop) if you don't want a window? Without a window (or timer as per post #2 and in some other cases) there are no messages to pump!


                              Michael Mattias
                              Tal Systems Inc.
                              Racine WI USA
                              mmattias@talsystems.com
                              http://www.talsystems.com

                              Comment


                              • #16
                                Michael - "application using SDK-style window creation and management" - Yes i see that now!

                                "there are no messages to pump".... Lets say I start up one of these "window less" windows... It dosnt have dialog messages to pump but it could as you said have timer or messages from other places.

                                Partly I am playing around seeing the difference between a simple DO LOOP and the message pump. I was thinking posting to a pump in a thread would be a neet way to get info into the thread without global vars and the need for the thread to always be looping through the globals....

                                Comment


                                • #17
                                  You do not send info to a "thread." You send info to a procedure.

                                  Partly I am playing around seeing the difference between a simple DO LOOP and the message pump.
                                  A message loop IS a simple DO loop. At least for those of us who have created at least one (1) application using SDK-style window creation and management it is.

                                  and the need for the thread to always be looping through the globals....
                                  Um... troubled code not shown, application not described. Style points deducted anyway for threatened "looping thru global [variables]"

                                  Describe challenge in English or other common language and ask for suggestions as to how to address in code!

                                  Michael Mattias
                                  Tal Systems Inc.
                                  Racine WI USA
                                  mmattias@talsystems.com
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    Michael, I have been lacking in explanation...

                                    Heres one example:

                                    Simultaneous TCP IP conversations with servers.

                                    The way I have done this in the past is open a lister TCP port and then accept requests as they come. Each request is assigned a file number and each request calls TCP NOTIFY READ CLOSE. At this point all READ events are signaled in the main thread. Then I start a thread for each read. So every connection is being read in its own thread. It works but might be over-using CREATE THREAD... As the thread ends at the end of each read.

                                    So.... Then I am thinking perhaps start the thread (and the function in the thread) and keep it running for the life of the TCP connection - kill the thread when we get a CLOSE from TCP NOTIFY. Of course TCP NOTIFY has to notify a CALLBACK function so the notification could be in the main thread or in the new thread - but the new thread would need a CALLBACK function to catch the TCP NOTIFY message.

                                    So in my mind the TCP RECV CALLBACK function would be in a "window less window" ie A thread with a message pump and callback function.
                                    Now, I could just have a second window, running in a separate thread, hidden that did TCP RECV tasks...

                                    Many of the TCP RECV (reads) take some time - thus the recv in a separate thread - also we write to disk or database in the same thread.

                                    So when I say "getting info to the thread" I should have said post a message to the hWin of the callback function in the thread I am wanting to communicate to.

                                    So, I am pondering from an architectural perspective - move all tcp out of the main (GUI) window / thread and put it in second window / thread. Or is my current way of CREATE THREAD for each read a reasonable way to go. Having the main window callback call the RECV_FUNCTION that creates the thread...

                                    I will post some small code bits after I play with it a bit more...

                                    Thanks!




                                    Comment

                                    Working...
                                    X