! HelloWin.f90 ! Compiled with: ! C:\>c:\gfortran\win64\bin\x86_64-pc-mingw32-gfortran -Wall HelloWin.f90 -oHelloWin -lgdi32 module mykinds implicit none integer, parameter :: ik1 = selected_int_kind(2) integer, parameter :: ik2 = selected_int_kind(4) integer, parameter :: ik4 = selected_int_kind(9) integer, parameter :: ik8 = selected_int_kind(18) integer, parameter :: sp = selected_real_kind(6,30) integer, parameter :: dp = selected_real_kind(15,300) end module mykinds module cheater use ISO_C_BINDING implicit none private public assignment(=) interface assignment(=) module procedure assign end interface assignment(=) contains subroutine assign(cptr, cintptr) type(C_PTR), intent(out) :: cptr integer(C_INTPTR_T), intent(in) :: cintptr call assign_level_1(assign_level_3, cptr, cintptr) end subroutine assign subroutine assign_level_1(sub3, cptr, cintptr) external sub3 type(C_PTR), intent(out) :: cptr integer(C_INTPTR_T), intent(in) :: cintptr call assign_level_2(sub3, cptr, cintptr) end subroutine assign_level_1 subroutine assign_level_2(sub3, cptr, cintptr) bind(C) interface subroutine sub3(cptr, cintptr) bind(C) use ISO_C_BINDING implicit none type(C_PTR), intent(out) :: cptr integer(C_INTPTR_T), intent(in), value :: cintptr end subroutine sub3 end interface type(C_PTR), intent(out) :: cptr integer(C_INTPTR_T), intent(in) :: cintptr call sub3(cptr, cintptr) end subroutine assign_level_2 subroutine assign_level_3(cptr, cintptr) bind(C) type(C_PTR), intent(out) :: cptr integer(C_LONG), intent(in), target :: cintptr cptr = C_LOC(cintptr) end subroutine assign_level_3 end module cheater module win32_types use ISO_C_BINDING implicit none private public WNDCLASSEX_T type, bind(C) :: WNDCLASSEX_T integer(C_INT) cbSize integer(C_INT) style type(C_FUNPTR) lpfnWndProc integer(C_INT) cbClsExtra integer(C_INT) cbWndExtra integer(C_INTPTR_T) hInstance integer(C_INTPTR_T) hIcon integer(C_INTPTR_T) hCursor integer(C_INTPTR_T) hbrBackground type(C_PTR) lpszMenuName type(C_PTR) lpszClassName integer(C_INTPTR_T) hIconSm end type WNDCLASSEX_T public POINT_T type, bind(C) :: POINT_T integer(C_LONG) x integer(C_LONG) y end type POINT_T public MSG_T type, bind(C) :: MSG_T integer(C_INTPTR_T) hwnd integer(C_INT) message integer(C_INTPTR_T) wParam integer(C_INTPTR_T) lParam integer(C_LONG) time type(POINT_T) pt end type MSG_T public RECT_T type, bind(C) :: RECT_T integer(C_LONG) left integer(C_LONG) top integer(C_LONG) right integer(C_LONG) bottom end type RECT_T public PAINTSTRUCT_T type, bind(C) :: PAINTSTRUCT_T integer(C_INTPTR_T) hdc integer(C_INT) fErase type(RECT_T) rcPaint integer(C_INT) fRestore integer(C_INT) fIncUpdate end type PAINTSTRUCT_T end module win32_types module win32 use mykinds use ISO_C_BINDING use win32_types implicit none private public GetModuleHandleA interface function GetModuleHandleA(lpModuleName) & bind(C,name='GetModuleHandleA') use ISO_C_BINDING implicit none integer(C_INTPTR_T) GetModuleHandleA character(kind=C_CHAR) lpModuleName(*) end function GetModuleHandleA end interface public GetCommandLineA interface function GetCommandLineA() & bind(C,name='GetCommandLineA') use ISO_C_BINDING implicit none integer(C_INTPTR_T) GetCommandLineA end function GetCommandLineA end interface public DefWindowProc interface function DefWindowProc(hwnd, iMsg, wParam, lParam) & bind(C,name='DefWindowProcA') use ISO_C_BINDING implicit none integer(C_LONG) DefWindowProc integer(C_INTPTR_T), value :: hwnd integer(C_INT), value :: iMsg integer(C_INTPTR_T), value :: wParam integer(C_INTPTR_T), value :: lParam end function DefWindowProc end interface public LoadIcon interface function LoadIcon(hInstance, lpIconName) & bind(C,name='LoadIconA') use ISO_C_BINDING implicit none integer(C_INTPTR_T) LoadIcon integer(C_INTPTR_T), value :: hInstance character(kind=C_CHAR) lpIconName(*) end function LoadIcon end interface public LoadCursor interface function LoadCursor(hInstance, lpIconName) & bind(C,name='LoadCursorA') use ISO_C_BINDING implicit none integer(C_INTPTR_T) LoadCursor integer(C_INTPTR_T), value :: hInstance character(kind=C_CHAR) lpIconName(*) end function LoadCursor end interface public GetStockObject interface function GetStockObject(fnObject) & bind(C,name='GetStockObject') use ISO_C_BINDING implicit none integer(C_INTPTR_T) GetStockObject integer(C_INT), value :: fnObject end function GetStockObject end interface public RegisterClassEx interface function RegisterClassEx(WndClass) & bind(C,name='RegisterClassExA') use ISO_C_BINDING use win32_types implicit none integer(C_SHORT) RegisterClassEx type(WNDCLASSEX_T) WndClass end function RegisterClassEx end interface ! Work around bug in libuser32.a ! public CreateWindow ! interface ! function CreateWindow(lpClassName, lpWindowName, dwStyle, & ! x, y, nWidth, nHeight, hwndParent, hMenu, hInstance, & ! lpParam) bind(C,name='CreateWindow') ! ! use ISO_C_BINDING ! implicit none ! integer(C_INTPTR_T) CreateWindow ! character(kind=C_CHAR) lpClassName(*) ! character(kind=C_CHAR) lpWindowName(*) ! integer(C_LONG), value :: dwStyle ! integer(C_INT), value :: x ! integer(C_INT), value :: y ! integer(C_INT), value :: nWidth ! integer(C_INT), value :: nHeight ! integer(C_INTPTR_T), value :: hWndParent ! integer(C_INTPTR_T), value :: hMenu ! integer(C_INTPTR_T), value :: hInstance ! type(C_PTR), value :: lpParam ! end function CreateWindow ! end interface public CreateWindowEx interface function CreateWindowEx(dwExStyle, lpClassName, & lpWindowName, dwStyle, x, y, nWidth, nHeight, & hwndParent, hMenu, hInstance, lpParam) & bind(C,name='CreateWindowExA') use ISO_C_BINDING implicit none integer(C_INTPTR_T) CreateWindowEx integer(C_LONG), value :: dwExStyle character(kind=C_CHAR) lpClassName(*) character(kind=C_CHAR) lpWindowName(*) integer(C_LONG), value :: dwStyle integer(C_INT), value :: x integer(C_INT), value :: y integer(C_INT), value :: nWidth integer(C_INT), value :: nHeight integer(C_INTPTR_T), value :: hWndParent integer(C_INTPTR_T), value :: hMenu integer(C_INTPTR_T), value :: hInstance type(C_PTR), value :: lpParam end function CreateWindowEx end interface public ShowWindow interface function ShowWindow(hWnd,nCmdShow) bind(C,name='ShowWindow') use ISO_C_BINDING implicit none integer(C_INT) ShowWindow integer(C_INTPTR_T), value :: hWnd integer(C_INT), value :: nCmdShow end function ShowWindow end interface public UpdateWindow interface function UpdateWindow(hWnd) bind(C,name='UpdateWindow') use ISO_C_BINDING implicit none integer(C_INT) UpdateWindow integer(C_INTPTR_T), value :: hWnd end function UpdateWindow end interface public GetMessage interface function GetMessage(lpMsg,hWnd,wMsgFilterMin,wMsgFilterMax) & bind(C,name='GetMessageA') use ISO_C_BINDING use win32_types implicit none integer(C_INT) GetMessage type(MSG_T) lpMsg integer(C_INTPTR_T), value :: hWnd integer(C_INT), value :: wMsgFilterMin integer(C_INT), value :: wMsgFilterMax end function GetMessage end interface public TranslateMessage interface function TranslateMessage(lpMsg) bind(C,name='TranslateMessage') use ISO_C_BINDING use win32_types implicit none integer(C_INT) TranslateMessage type(MSG_T) lpMsg end function TranslateMessage end interface public DispatchMessage interface function DispatchMessage(lpMsg) bind(C,name='DispatchMessageA') use ISO_C_BINDING use win32_types implicit none integer(C_INT) DispatchMessage type(MSG_T) lpMsg end function DispatchMessage end interface public ExitProcess interface subroutine ExitProcess(uExitCode) bind(C,name='ExitProcess') use ISO_C_BINDING implicit none integer(C_INT), value :: uExitCode end subroutine ExitProcess end interface public BeginPaint interface function BeginPaint(hwnd,lpPaint) bind(C,name='BeginPaint') use ISO_C_BINDING use win32_types implicit none integer(C_INTPTR_T) BeginPaint integer(C_INTPTR_T), value :: hwnd type(PAINTSTRUCT_T) lpPaint end function BeginPaint end interface public GetClientRect interface function GetClientRect(hwnd,lpRect) bind(C,name='GetClientRect') use ISO_C_BINDING use win32_types implicit none integer(C_INTPTR_T) GetClientRect integer(C_INTPTR_T), value :: hwnd type(RECT_T) lpRect end function GetClientRect end interface public DrawText interface function DrawText(hdc, lpString, nCount, lpRect, & uFormat) bind(C,name='DrawTextA') use ISO_C_BINDING use win32_types implicit none integer(C_INT) DrawText integer(C_INTPTR_T), value :: hdc character(kind=C_CHAR) lpString integer(C_INT), value :: nCount type(RECT_T) lpRect integer(C_INT), value :: uFormat end function DrawText end interface public EndPaint interface function EndPaint(hwnd,lpPaint) bind(C,name='EndPaint') use ISO_C_BINDING use win32_types implicit none integer(C_INT) EndPaint integer(C_INTPTR_T), value :: hwnd type(PAINTSTRUCT_T) lpPaint end function EndPaint end interface public PostQuitMessage interface subroutine PostQuitMessage(nExitCode) bind(C,name='PostQuitMessage') use ISO_C_BINDING implicit none integer(C_INT), value :: nExitCode end subroutine PostQuitMessage end interface end module win32 module procs use win32 use win32_types use ISO_C_BINDING implicit none private public WndProc contains function WndProc(hwnd, iMsg, wParam, lParam) bind(C) integer(C_LONG) WndProc integer(C_INTPTR_T), value :: hwnd integer(C_INT), value :: iMsg integer(C_INTPTR_T), value :: wParam integer(C_INTPTR_T), value :: lParam integer(C_INTPTR_T) hdc type(PAINTSTRUCT_T) ps type(RECT_T) rect integer(C_INT) result4 character(kind=C_CHAR) message*(80) select case(iMsg) case(1) ! WM_CREATE WndProc = 0 return case(15) ! WM_PAINT hdc = BeginPaint(hwnd, ps) result4 = GetClientRect(hwnd, rect) message = 'Hello, gfortran!'//achar(0) result4 = DrawText(hdc, message, -1, rect, 37) result4 = EndPaint(hwnd, ps) WndProc = 0 return case(2) ! WM_DESTROY call PostQuitMessage(0) WndProc = 0 return end select WndProc = DefWindowProc(hwnd, iMsg, wParam, lParam) end function WndProc end module procs program WinMain use mykinds use win32 use win32_types use procs use cheater use ISO_C_BINDING implicit none character(kind=C_CHAR), pointer :: pcNull(:) integer(C_INTPTR_T) hInstance integer(C_INTPTR_T) szCommandLine type(C_PTR) pCommandLine type(WNDCLASSEX_T) WndClass type(C_PTR) pDefault character(kind=C_CHAR), pointer :: cDefault(:) character(kind=C_CHAR), target :: szAppName*(80) integer(C_SHORT) result2 integer(C_INTPTR_T) hwnd character(kind=C_CHAR), target :: szWindowCaption*(80) integer(C_INT) result4 type(MSG_T) msg integer(C_INT) argh4 call C_F_POINTER(C_NULL_PTR,pcNull,[0]) hInstance = GetModuleHandleA(pcNull) szCommandLine = GetCommandLineA() pCommandLine = szCommandLine pDefault = 32512_C_INTPTR_T call C_F_POINTER(pDefault,cDefault,[0]) szAppName = 'HelloWin'//achar(0) WndClass%cbSize = size(transfer(Wndclass,[0_ik1])) WndClass%style = 3 ! ior(CS_HREDRAW, CS_VREDRAW) WndClass%lpfnWndProc = C_FUNLOC(WndProc) WndClass%cbClsExtra = 0 WndClass%cbWndExtra = 0 WndClass%hInstance = hInstance WndClass%hIcon = LoadIcon(0_C_INTPTR_T, cDefault) ! IDI_APPLICATION WndClass%hCursor = LoadCursor(0_C_INTPTR_T, cDefault) ! IDC_ARROW WndClass%hbrBackground = GetStockObject(0) ! WHITE_BRUSH WndClass%lpszMenuName = C_NULL_PTR WndClass%lpszClassName = C_LOC(szAppName(1:1)) WndClass%hIconSm = LoadIcon(0_C_INTPTR_T, cDefault) ! IDI_APPLICATION result2 = RegisterClassEx(WndClass) szWindowCaption = 'The Hello Program'//achar(0) ! Workaround for bug ! hwnd = CreateWindow(szAppName, szWindowCaption, & ! 13565952, -2147483648, -2147483648, -2147483648, & ! -2147483648, 0_C_INTPTR_T, 0_C_INTPTR_T, hInstance, & ! C_NULL_PTR) argh4 = -2147483647-1 ! Workaround for libuser32.a bug ! hwnd = CreateWindow(szAppName, szWindowCaption, & ! 13565952, argh4, argh4, argh4, argh4, 0_C_INTPTR_T, & ! 0_C_INTPTR_T, hInstance, C_NULL_PTR) hwnd = CreateWindowEx(0, szAppName, szWindowCaption, & 13565952, argh4, argh4, argh4, argh4, 0_C_INTPTR_T, & 0_C_INTPTR_T, hInstance, C_NULL_PTR) result4 = ShowWindow(hwnd, 10) ! SW_SHOWDEFAULT result4 = UpdateWindow(hwnd) ! Workaround for bug do while(GetMessage(msg, 0_C_INTPTR_T, 0, 0) /= 0) result4 = TranslateMessage(msg) result4 = DispatchMessage(msg) end do call ExitProcess(int(msg%wParam, C_INT)) end program WinMain