fortran66のブログ

fortran について書きます。

スヌーピーカレンダー

ラインプリンタの重ね打ちを使っているので、Windowsのグラフィックでラインプリンタ動作を再現するように作ってみた試し。もう少し完成度をあげたい。

ラインプリンタ出力+α

スヌーピーカレンダーデータは別プログラム。過去日記参照。
テスト 未完成↓

MODULE uho_win
USE ifwina
USE ifwinty
USE ifmt, ONLY : RTL_CRITICAL_SECTION
IMPLICIT NONE
TYPE :: t_wnd
 INTEGER (HANDLE) :: hWnd
 INTEGER (HANDLE) :: hDC
 INTEGER (LPINT)  :: hThread
 INTEGER         :: id
 INTEGER (HANDLE) :: hPen
 CHARACTER (LEN = 80) :: title = 'Fortran Plot'
 INTEGER          :: nsize_x = 320, nsize_y = 240  
 REAL             :: xmin = 0.0, xmax = 1.0, ymin = 0.0, ymax = 1.0   
END TYPE
TYPE (t_wnd) :: wnd
TYPE (RTL_CRITICAL_SECTION) :: lpCriticalSection
CONTAINS
!--------------------------------------------------------------------------------
INTEGER FUNCTION WinMain( hInstance, hPrevInstance, lpszCmdLine, nCmdShow, wnd)
IMPLICIT NONE
INTEGER (HANDLE), INTENT(IN) :: hInstance, hPrevInstance 
INTEGER (LPSTR) , INTENT(IN) :: lpszCmdLine
INTEGER (SINT)  , INTENT(IN) :: nCmdShow
TYPE (t_wnd)    , INTENT(IN OUT) :: wnd
! Variables
LOGICAL, SAVE :: qfirst = .TRUE.
TYPE (T_WNDCLASS) :: wc
TYPE (T_MSG)      :: mesg
INTEGER (HANDLE)  :: hWndMain
INTEGER (BOOL)    :: iretb
CHARACTER (LEN = 256) :: ClassName = "Fortran"C
INTEGER :: noffset_x, noffset_y !side line = 6, title bar = 25
!  Init   Main window
noffset_x = 2 * GetSystemMetrics(SM_CXFIXEDFRAME)
noffset_y = 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION)
!
WinMain = -1 ! Error code 
IF (qfirst) THEN
wc%lpszClassName = LOC(ClassName)
wc%lpfnWndProc   = LOC(MainWndProc)               ! CALL BACK procedure name
wc%style         = IOR(CS_VREDRAW , CS_HREDRAW)
wc%hInstance     = hInstance
wc%hIcon         = NULL   
wc%hCursor       = LoadCursor( NULL, IDC_ARROW )
wc%hbrBackground = ( COLOR_WINDOW + 1 )
IF (RegisterClass(wc) == 0) RETURN
qfirst = .FALSE.
END IF
!Init instance
WinMain = -2 ! Error code 
hWndMain = CreateWindowEx(  0, ClassName,                        &
                            TRIM(wnd%title)//''C,               &
                            INT(IOR(WS_OVERLAPPED, WS_SYSMENU)), &
                            CW_USEDEFAULT, CW_USEDEFAULT,        &
                            wnd%nsize_x + noffset_x,            &
                            wnd%nsize_y + noffset_y,            &
                            0,                                &
                            0,                                &
                            hInstance,                         &
                            LOC(wnd)                           )
IF (hWndMain == 0) RETURN
iretb = ShowWindow( hWndMain, nCmdShow )
iretb = UpdateWindow( hWndMain )
! Message Loop
DO WHILE ( GetMessage (mesg, NULL, 0, 0) ) 
 iretb = TranslateMessage( mesg )
 iretb = DispatchMessage(  mesg )
END DO
WinMain = mesg%wParam
RETURN
END FUNCTION WinMain
!----------------------------------------------------------
INTEGER*4 FUNCTION MainWndProc( hWnd, mesg, wParam, lParam ) 
!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS : 'MainWndProc' :: MainWndProc
USE IFMT
IMPLICIT NONE
INTEGER (HANDLE) , INTENT(IN) :: hWnd
INTEGER (UINT)   , INTENT(IN) :: mesg
INTEGER (fwParam), INTENT(IN) :: wParam
INTEGER (flParam), INTENT(IN) :: lParam
!
INTEGER (HANDLE) :: hDC, hBmp
INTEGER (BOOL)   :: iretb
TYPE (T_PAINTSTRUCT)   :: ps
TYPE (T_RECT)         :: rc
!
MainWndProc = 0
SELECT CASE ( mesg )
   CASE (WM_CREATE)
     hDC      = GetDC(hWnd)
     iretb    = GetClientRect(hWnd, rc)
     hBmp     = CreateCompatibleBitmap(hDC, rc%right - rc%left, rc%bottom - rc%top)
     wnd%hWnd = hWnd
     wnd%hDC  = CreateCompatibleDC(hDC)
     iretb    = SelectObject(wnd%hDC, hBmp)
     iretb    = PatBlt(wnd%hDC, 0, 0, rc%right - rc%left, rc%bottom - rc%top, WHITENESS)
     iretb    = ReleaseDC(hWnd, hDC)
     iretb    = DeleteObject(hBmp)
   CASE (WM_DESTROY)
     iretb = DeleteObject( wnd%hDC )
     CALL PostQuitMessage( 0 )
   CASE (WM_PAINT)
     CALL EnterCriticalSection(LOC(lpCriticalSection))
     hDC    = BeginPaint(    wnd%hWnd, ps )
     iretb  = GetClientRect( wnd%hWnd, rc )
     iretb  = BitBlt(hDC, 0, 0, rc%right  - rc%left, rc%bottom - rc%top, wnd%hDC, 0, 0, SRCCOPY)
     iretb  = EndPaint( wnd%hWnd, ps )
     CALL LeaveCriticalSection(LOC(lpCriticalSection))
   CASE (WM_LBUTTONDOWN)
     WRITE(*, *) 'LBUTTON ', TRIM(wnd%title), wnd%hWnd
   CASE (WM_RBUTTONDOWN)
     WRITE(*, *) 'RBUTTON ', TRIM(wnd%title), wnd%hWnd
   CASE DEFAULT
     MainWndProc = DefWindowProc( hWnd, mesg, wParam, lParam )
END SELECT 
RETURN
END FUNCTION MainWndProc
!-------------------------------------------------------------------------------
END MODULE uho_win
!=================================================================================
MODULE uhoplot
USE uho_win
CONTAINS
!-------------------------------------------------------------------------------------
INTEGER (HANDLE) FUNCTION get_DosHndl()
IMPLICIT NONE
INTERFACE
 FUNCTION GetConsoleWindow() ! non-existent in IFORTxx.MOD
 USE ifwinty
 INTEGER (HANDLE) :: GetConsoleWindow
 !DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'GetConsoleWindow' :: GetConsoleWindow
 END FUNCTION
END INTERFACE
get_DosHndl = GetConsoleWindow()
RETURN
END FUNCTION get_DosHndl
!-------------------------------------------------------------------------------------
SUBROUTINE gr_on(text, nx, ny)
USE IFMT ! multithread module
IMPLICIT NONE
CHARACTER (LEN = *), INTENT(IN), OPTIONAL :: text
INTEGER            , INTENT(IN), OPTIONAL :: nx, ny
INTEGER (BOOL)    :: iretb
INTEGER (HANDLE)  :: hBmp
INTEGER (LPDWORD) :: id
TYPE (T_RECT)    :: rc
IF (PRESENT(text)) wnd%title   = TRIM(text)
IF (PRESENT(nx)  ) wnd%nsize_x = nx
IF (PRESENT(ny)  ) wnd%nsize_y = ny
CALL InitializeCriticalSection(LOC(lpCriticalSection))
wnd%hThread = CreateThread(0, 0, Thread_Proc, LOC(wnd), CREATE_SUSPENDED, id)
wnd%id      = id
iretb       = SetThreadPriority(wnd%hThread, THREAD_PRIORITY_BELOW_NORMAL)
iretb       = ResumeThread(wnd%hThread)
CALL Sleep(100) ! wait for Window initialization 
iretb = GetClientRect(wnd%hWnd, rc)
hBmp  = CreateCompatibleBitmap(wnd%hDC, rc%right - rc%left, rc%bottom - rc%top)
iretb = SelectObject(wnd%hDC, hBmp)
iretb = DeleteObject(hBmp)
iretb = PatBlt(wnd%hDC, 0, 0, rc%right - rc%left, rc%bottom - rc%top, WHITENESS)
wnd%hPen = CreatePen(PS_SOLID, 1, 0)
RETURN
END SUBROUTINE gr_on
!-------------------------------------------------------------------------------------
SUBROUTINE gr_off(isec)
USE IFMT ! Module for multithread
IMPLICIT NONE
INTEGER (DWORD), INTENT(IN), OPTIONAL :: isec 
INTEGER (BOOL)  :: iretb
INTEGER (DWORD) :: iwait
IF (PRESENT(isec)) THEN
 iwait = isec * 1000
ELSE
 iwait = INFINITE
END IF 
CALL gr_show() ! 
iretb = DeleteObject(wnd%hPen) 
iretb = WaitForSingleObject(wnd%hThread, iwait)
iretb = CloseHandle(wnd%hThread)
iretb = PostMessage(wnd%hWnd, WM_DESTROY, NULL, NULL)
wnd%hThread = NULL
CALL DeleteCriticalSection(LOC(lpCriticalSection))
RETURN
END SUBROUTINE gr_off
!-------------------------------------------------------------------------------------
INTEGER (LONG) FUNCTION Thread_Proc(lp_ThreadParameter)
!DEC$ ATTRIBUTES STDCALL, ALIAS:"_thread_proc" :: Thread_Proc
IMPLICIT NONE
INTEGER (LPINT), INTENT(IN) :: lp_ThreadParameter
INTEGER :: hInst
TYPE (t_wnd) :: wnd
POINTER (p_wnd, wnd) ! non-standard fortran
p_wnd       = lp_ThreadParameter
hInst       = GetModuleHandle(NULL) 
Thread_Proc = WinMain(hInst, NULL, NULL, SW_SHOWNORMAL, wnd)
RETURN
END FUNCTION Thread_Proc
!-------------------------------------------------------------------------------------
SUBROUTINE gr_dot(ix, iy, icol)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ix, iy
INTEGER, INTENT(IN) :: icol
INTEGER (BOOL):: iretb
CALL EnterCriticalSection(LOC(lpCriticalSection))
iretb = SetPixel(wnd%hDC, ix, iy, icol)
CALL LeaveCriticalSection(LOC(lpCriticalSection))
RETURN
END SUBROUTINE gr_dot
!-------------------------------------------------------------------------------------
SUBROUTINE gr_move(ix, iy)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ix, iy
INTEGER (BOOL):: iretb
CALL EnterCriticalSection(LOC(lpCriticalSection))
iretb = MoveToEx(wnd%hDC, ix, iy, NULL)
CALL LeaveCriticalSection(LOC(lpCriticalSection))
RETURN
END SUBROUTINE gr_move
!-------------------------------------------------------------------------------------
SUBROUTINE gr_line(ix, iy)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ix, iy
INTEGER (BOOL):: iretb
CALL EnterCriticalSection(LOC(lpCriticalSection))
iretb = LineTo(wnd%hDC, ix, iy)
CALL LeaveCriticalSection(LOC(lpCriticalSection))
RETURN
END SUBROUTINE gr_line
!-------------------------------------------------------------------------------------
SUBROUTINE gr_show()
IMPLICIT NONE
INTEGER (BOOL):: iretb
iretb = InvalidateRect(wnd%hWnd, NULL, FALSE)
RETURN
END SUBROUTINE gr_show
!-------------------------------------------------------------------------------------
SUBROUTINE gr_pencol(icol)
IMPLICIT NONE
INTEGER, INTENT(IN) :: icol
INTEGER :: iretb
CALL EnterCriticalSection(LOC(lpCriticalSection))
iretb    = DeleteObject(wnd%hPen) 
wnd%hPen = CreatePen(PS_SOLID, 1, icol)
iretb    = SelectObject(wnd%hDC, wnd%hPen)
CALL LeaveCriticalSection(LOC(lpCriticalSection))
RETURN
END SUBROUTINE gr_pencol
!-------------------------------------------------------------------------------------
SUBROUTINE gr_text(ix, iy, txt, icol)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ix, iy
CHARACTER (LEN = *), INTENT(IN) :: txt
INTEGER, INTENT(IN), OPTIONAL :: icol
INTEGER (BOOL)   :: iretb
INTEGER (HANDLE) :: hFont

IF ( PRESENT(icol) ) iretb = SetTextColor(wnd%hDC, icol) 
CALL EnterCriticalSection(LOC(lpCriticalSection))
iretb = SetBkMode(wnd%hDC, TRANSPARENT)

hFont = CreateFont( 2 , 2 , 0 , 0 ,FW_DONTCARE , FALSE , FALSE , FALSE ,  &
			      DEFAULT_CHARSET , OUT_DEFAULT_PRECIS ,           &
			      CLIP_DEFAULT_PRECIS , PROOF_QUALITY ,           &
			      IOR(FIXED_PITCH,  FF_ROMAN) , NULL       		)
iretb = SelectObject(wnd%hdc , hFont)
iretb = TextOut(wnd%hDC, ix, iy, txt, LEN_TRIM(txt))
iretb = SelectObject(wnd%hdc , GetStockObject(SYSTEM_FONT))
iretb = DeleteObject(hFont)

CALL LeaveCriticalSection(LOC(lpCriticalSection))
RETURN
END SUBROUTINE gr_text
!-------------------------------------------------------------------------------------
INTEGER FUNCTION irgb(ir, ig, ib)
IMPLICIT NONE
INTEGER, INTENT(IN) :: ir, ig, ib
irgb = ir + (ig + (ib * 256)) * 256
RETURN
END FUNCTION irgb
!-------------------------------------------------------------------------------------
END MODULE uhoplot
!=====================================================================================
PROGRAM ABE3
USE uhoplot
INTEGER :: ix, iy, ic
character :: text*136
CALL gr_on('snoopy', 1200, 1000)
CALL gr_pencol(irgb(0, 0, 0))
!
ix = 0
iy = 0
ic = 0
open(UNIT=7,FILE='SNPCAL.OUT',STATUS='old')
    read(7, '(a)', end = 999) text ! skip first FF
    do 
      read(7, '(a)', end = 999) text
      select case(text(1:1))
      case ('0')
        ix = 300 * ic
        iy = iy + 36
        text(1:1) = ' '
        CALL gr_text(ix, iy, text, irgb(0, 0, 0) )
      case ('1')
        if ( iy > 800 ) then 
          ic = ic + 1
          iy = 0
        end if          
        ix = 300 * ic
        iy = iy + 20
        text(1:1) = ' '
        CALL gr_text(ix, iy, text, irgb(0, 0, 0) )
      case ('+')
        ix = 300 * ic
        text(1:1) = ' '
        CALL gr_text(ix, iy, text, irgb(0, 0, 0) )
      case default
        CALL gr_text(ix, iy, text, irgb(0, 0, 0) )
        iy = iy + 2 !18
      end select
    end do
 999 continue 
!
CALL gr_show()
CALL gr_off()
STOP
CONTAINS
!------------------------------------------------
SUBROUTINE line(x, y, ipen)
IMPLICIT NONE
REAL   , INTENT(IN) :: x, y
INTEGER, INTENT(IN) :: ipen
INTEGER (BOOL):: iretb
INTEGER :: ix, iy
ix =  INT(x * 3.0 + 250.0)
iy = -INT(y * 3.0 + 100.0) + 590 
IF (ipen == 1) THEN
 CALL gr_line(ix, iy)
ELSE
 CALL gr_move(ix, iy)
END IF
RETURN
END SUBROUTINE line
!------------------------------------------------
END PROGRAM abe3