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 IF (PRESENT(icol)) iretb = SetTextColor(wnd%hDC, icol) CALL EnterCriticalSection(LOC(lpCriticalSection)) iretb = TextOut(wnd%hDC, ix, iy, txt, LEN_TRIM(txt)) 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 :: i, j CALL gr_on('Abe-san', 500, 600) CALL gr_pencol(irgb(0, 0, 0)) ! chin chin CALL line( 0.0, 32.0, 0) CALL line( 0.0, 35.0, 1) ! collar CALL line( 8.0, 0.0, 0) CALL line( 22.0, 25.0, 1) CALL line( 30.0, 55.0, 1) CALL line( 19.0, 0.0, 0) CALL line( 25.0, 10.0, 1) CALL line( 47.0, 20.0, 1) CALL line( 35.0, 40.0, 1) CALL line( 55.0, 35.0, 1) CALL line( 35.0, 40.0, 0) CALL line( 30.0, 55.0, 1) CALL line( 13.0, 20.0, 0) CALL line( 24.0, 44.0, 1) CALL line( -8.0, 0.0, 0) CALL line(-22.0, 25.0, 1) CALL line(-30.0, 55.0, 1) CALL line(-19.0, 0.0, 0) CALL line(-25.0, 10.0, 1) CALL line(-47.0, 20.0, 1) CALL line(-35.0, 40.0, 1) CALL line(-55.0, 35.0, 1) CALL line(-35.0, 40.0, 0) CALL line(-30.0, 55.0, 1) CALL line(-13.0, 20.0, 0) CALL line(-24.0, 44.0, 1) ! CALL line( 0.0, 26.0, 0) CALL line( 4.0, 26.0, 1) CALL line( 14.0, 30.0, 1) CALL line( 24.0, 44.0, 1) CALL line( 30.0, 55.0, 1) CALL line( 33.0, 65.0, 1) CALL line( 33.0, 120.0, 1) CALL line( 2.0, 120.0, 1) CALL line( 2.0, 115.0, 1) CALL line( 0.0, 106.0, 1) CALL line( -2.0, 103.0, 1) ! CALL line( 0.0, 26.0, 0) CALL line( -4.0, 26.0, 1) CALL line(-14.0, 30.0, 1) CALL line(-24.0, 44.0, 1) CALL line(-30.0, 55.0, 1) CALL line(-33.0, 65.0, 1) CALL line(-33.0, 120.0, 1) CALL line( 0.0, 120.0, 1) CALL line( 0.0, 110.0, 1) CALL line( -2.0, 103.0, 1) !right ear CALL line( 33.0, 65.0, 0) CALL line( 42.0, 77.0, 1) CALL line( 42.0, 89.0, 1) CALL line( 40.0, 93.0, 1) CALL line( 36.0, 93.0, 1) CALL line( 34.0, 86.0, 1) CALL line( 33.0, 84.0, 1) CALL line( 34.0, 86.0, 0) CALL line( 36.0, 84.0, 1) CALL line( 36.0, 74.0, 1) CALL line( 33.0, 69.0, 1) !left ear CALL line(-33.0, 65.0, 0) CALL line(-42.0, 77.0, 1) CALL line(-42.0, 89.0, 1) CALL line(-40.0, 93.0, 1) CALL line(-36.0, 93.0, 1) CALL line(-34.0, 86.0, 1) CALL line(-33.0, 84.0, 1) CALL line(-34.0, 86.0, 0) CALL line(-36.0, 84.0, 1) CALL line(-36.0, 74.0, 1) CALL line(-33.0, 69.0, 1) ! hair CALL line( 40.0, 93.0, 0) CALL line( 40.0, 120.0, 1) CALL line( 33.0, 135.0, 1) CALL line( 14.0, 147.0, 1) CALL line(-14.0, 147.0, 1) CALL line(-33.0, 135.0, 1) CALL line(-40.0, 120.0, 1) CALL line(-40.0, 93.0, 1) ! mouth CALL line(-15.0, 54.0, 0) CALL line(-14.0, 53.0, 1) CALL line( -6.0, 53.0, 1) CALL line( -5.0, 52.0, 1) CALL line( -1.0, 52.0, 0) CALL line( 7.0, 53.0, 1) CALL line( 10.0, 52.0, 1) CALL line( 11.0, 53.0, 1) ! CALL line( -6.0, 45.0, 0) CALL line( -5.0, 44.0, 1) CALL line( 5.0, 44.0, 1) CALL line( 6.0, 45.0, 0) ! nose CALL line( 2.0, 65.0, 0) CALL line( 2.0, 64.0, 1) CALL line( 0.0, 62.0, 1) CALL line( -4.0, 64.0, 1) CALL line( -6.0, 62.0, 1) CALL line( 0.0, 59.0, 1) CALL line( 5.0, 61.0, 1) CALL line( 5.0, 66.0, 1) CALL line( 4.0, 66.0, 1) CALL line( 2.0, 68.0, 1) CALL line( 2.0, 87.0, 1) CALL line( 6.0, 92.0, 1) CALL line( 5.0, 95.0, 1) ! CALL line( 3.0, 72.0, 0) CALL line( 3.0, 86.0, 1) CALL line( 4.0, 87.0, 1) CALL line( 7.0, 77.0, 1) CALL line( 3.0, 72.0, 1) ! right eye CALL line( 5.0, 95.0, 0) CALL line( 7.0, 97.0, 1) CALL line( 30.0, 97.0, 1) CALL line( 32.0, 93.0, 1) CALL line( 25.0, 94.0, 1) CALL line( 12.0, 94.0, 1) CALL line( 5.0, 95.0, 1) CALL line( 10.0, 93.0, 0) CALL line( 12.0, 94.0, 1) CALL line( 29.0, 90.0, 0) CALL line( 25.0, 94.0, 1) ! CALL line( 14.0, 85.0, 0) CALL line( 18.0, 85.0, 1) CALL line( 19.0, 84.0, 1) CALL line( 20.0, 85.0, 1) CALL line( 23.0, 84.0, 1) ! CALL line( 10.0, 83.0, 0) CALL line( 18.0, 82.0, 1) CALL line( 20.0, 81.0, 1) ! CALL line( 18.0, 90.0, 0) CALL line( 20.0, 90.0, 1) CALL line( 20.0, 92.0, 1) CALL line( 18.0, 92.0, 1) CALL line( 18.0, 90.0, 1) ! CALL line( 10.0, 91.0, 0) CALL line( 15.0, 94.0, 1) CALL line( 23.0, 94.0, 1) CALL line( 27.0, 91.0, 1) CALL line( 29.0, 87.0, 1) CALL line( 28.0, 87.0, 1) CALL line( 27.0, 90.0, 1) CALL line( 23.0, 93.0, 1) CALL line( 23.0, 89.0, 1) CALL line( 21.0, 87.0, 1) CALL line( 17.0, 87.0, 1) CALL line( 15.0, 89.0, 1) CALL line( 15.0, 91.0, 1) CALL line( 16.0, 93.0, 1) CALL line( 11.0, 90.0, 1) CALL line( 10.0, 91.0, 1) ! left eye CALL line(-33.0, 95.0, 0) CALL line(-30.0, 99.0, 1) CALL line(-12.0, 99.0, 1) CALL line( -7.0, 96.0, 1) CALL line(-10.0, 94.0, 1) CALL line(-14.0, 95.0, 1) CALL line(-33.0, 95.0, 1) CALL line(-11.0, 92.0, 0) CALL line(-14.0, 95.0, 1) ! CALL line(-23.0, 82.0, 0) CALL line(-21.0, 81.0, 1) CALL line(-14.0, 84.0, 1) ! CALL line(-27.0, 86.0, 0) CALL line(-21.0, 85.0, 1) CALL line(-15.0, 86.0, 1) ! CALL line(-29.0, 90.0, 0) CALL line(-25.0, 94.0, 1) CALL line(-15.0, 94.0, 1) CALL line(-12.0, 91.0, 1) CALL line(-13.0, 90.0, 1) CALL line(-16.0, 92.0, 1) CALL line(-17.0, 90.0, 1) CALL line(-18.0, 87.0, 1) CALL line(-22.0, 87.0, 1) CALL line(-24.0, 89.0, 1) CALL line(-24.0, 92.0, 1) CALL line(-28.0, 89.0, 1) CALL line(-29.0, 90.0, 1) ! CALL line(-19.0, 90.0, 0) CALL line(-21.0, 90.0, 1) CALL line(-21.0, 92.0, 1) CALL line(-19.0, 92.0, 1) CALL line(-19.0, 90.0, 1) ! CALL gr_text(200, 10, 'やらないか', irgb(0, 155, 255) ) ! 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
H20(2008)-2-21 微妙に修正。
プロジェクトはコンソール用で、オプションはランタイムライブラリをマルチスレッド対応へ。