Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

How to change console window size programmatically

jirina
Nouveau contributeur I
2 229 Visites

Is there a way how I can change the size of my application's console window programmatically? I know I can change the console window size (and other properties like font, color, or screen buffer size) manually, but I would like to automatically change the size to the desired one once the application starts running.

0 Compliments
1 Solution
IanH
Contributeur émérite III
2 229 Visites

Yes - the error is due to a clash between use associated symbols.  You can use the ONLY feature of USE, or the rename feature, on ifport perhaps, to avoid the clash.

Here is an example using SetConsoleWindowInfo.  Unlike Andrew's example, this cannot control the location of the window, just its size. 

Note that a BOOL value is best considered a kind of integer (some API's even return BOOL values that are different from the TRUE or FALSE named constants (which are not necessarily same things as .TRUE. and .FALSE. logical literal constants)), and that 120 rows of console display requires quite a tall display monitor or a rather squished font.

program set_window
  use ifwin
  implicit none
  
  integer(HANDLE) :: output_handle
  integer(BOOL) :: bool_result
  
  type(T_CONSOLE_SCREEN_BUFFER_INFO) :: cBufInfoLoc
  type(T_SMALL_RECT) :: srWindowLoc
  
  output_handle = GetStdHandle(STD_OUTPUT_HANDLE)
  bool_result = GetConsoleScreenBufferInfo(output_handle, cBufInfoLoc)
  if (bool_result == 0) then
    print "(i0)", GetLastError()
    error stop 'GetConsoleScreenBufferInfo failed'
  end if
  
  srWindowLoc%left = 0
  srWindowLoc%top = 0
  srWindowLoc%right = min(79, cBufInfoLoc%dwMaximumWindowSize%X - 1)
  srWindowLoc%bottom = min(120, cBufInfoLoc%dwMaximumWindowSize%Y - 1)
  bool_result = SetConsoleWindowInfo(output_handle, TRUE, srWindowLoc)
  if (bool_result == 0) then
    print "(i0)", GetLastError()
    error stop 'SetConsoleWindowInfo failed'
  end if
end program set_window

 

Voir la solution dans l'envoi d'origine

0 Compliments
6 Réponses
IanH
Contributeur émérite III
2 229 Visites

Have a look at the console support API, in particular SetConsoleWindowInfo.

0 Compliments
jirina
Nouveau contributeur I
2 229 Visites

Thank you for pointing me in the right direction. I am trying following to set console window icon (this works well) and to change the console window size (this does not work):

use ifport
use ifwin

        interface
          function SetConsoleIcon ( hIcon )
          use ifwinty
          integer(BOOL) :: SetConsoleIcon
          integer(DWORD) :: hIcon
          !dec$ attributes default, stdcall :: SetConsoleIcon
          end function
        end interface

        integer,parameter :: IDI_ICON_MYAPP=101
        integer(kind=HANDLE) hModule, hLib
        integer hMainIcon, lRet
        pointer ( SetConsoleF1, SetConsoleIcon )

        type(T_CONSOLE_SCREEN_BUFFER_INFO) cBufInfoLoc
        type(T_SMALL_RECT) :: srWindowLoc
        logical*4 :: lStatLoc
        integer(DWORD) :: lastError

        hLib = LoadLibrary ( 'Kernel32.dll'C )
        SetConsoleF1 = GetProcAddress ( hLib, 'SetConsoleIcon'C )
        hModule = GetModuleHandle(0)
        hMainIcon = LoadIcon ( hModule, MAKEINTRESOURCE(IDI_ICON_MYAPP) )
        lRet = SetConsoleIcon ( hMainIcon )
        lRet = FreeLibrary ( hLib )

        hModule = GetStdHandle(STD_OUTPUT_HANDLE)
        lStatLoc =  GetConsoleScreenBufferInfo ( hModule, cBufInfoLoc )
        if ( lStatLoc ) then
          srWindowLoc.top = 0
          srWindowLoc.left = 0
          srWindowLoc.right = 79
          srWindowLoc.bottom = 120
          lStatLoc = SetConsoleWindowInfo ( hModule, .TRUE., srWindowLoc )
          if ( .NOT.lStatLoc ) then
            lastError = GetLastError ( )
          endif
        endif

GetConsoleScreenBufferInfo works well and cBufInfoLoc contain correct information about the console window size. However, SetConsoleWindowInfo returns false and I am not able to use the GetLastError function, because I get compiler error #6405: The same named entity from different modules and/or program units cannot be referenced. Is this because I use both ifport and ifwin? Is there any documentation with a list of what both of them contain?

0 Compliments
andrew_4619
Contributeur émérite III
2 229 Visites
        bret = SetWindowPos(GetConsoleWindow(),int(HWND_TOP,handle), wrect2%left, wrect2%top, &
                            wrect2%right-wrect2%left, wrect2%bottom -wrect2%top ,SWP_SHOWWINDOW)

 

0 Compliments
andrew_4619
Contributeur émérite III
2 229 Visites

The one above works for me. You don't need to loadlibrary for kernel32 it will resolve as you use it by default with all windowing apps.

0 Compliments
IanH
Contributeur émérite III
2 230 Visites

Yes - the error is due to a clash between use associated symbols.  You can use the ONLY feature of USE, or the rename feature, on ifport perhaps, to avoid the clash.

Here is an example using SetConsoleWindowInfo.  Unlike Andrew's example, this cannot control the location of the window, just its size. 

Note that a BOOL value is best considered a kind of integer (some API's even return BOOL values that are different from the TRUE or FALSE named constants (which are not necessarily same things as .TRUE. and .FALSE. logical literal constants)), and that 120 rows of console display requires quite a tall display monitor or a rather squished font.

program set_window
  use ifwin
  implicit none
  
  integer(HANDLE) :: output_handle
  integer(BOOL) :: bool_result
  
  type(T_CONSOLE_SCREEN_BUFFER_INFO) :: cBufInfoLoc
  type(T_SMALL_RECT) :: srWindowLoc
  
  output_handle = GetStdHandle(STD_OUTPUT_HANDLE)
  bool_result = GetConsoleScreenBufferInfo(output_handle, cBufInfoLoc)
  if (bool_result == 0) then
    print "(i0)", GetLastError()
    error stop 'GetConsoleScreenBufferInfo failed'
  end if
  
  srWindowLoc%left = 0
  srWindowLoc%top = 0
  srWindowLoc%right = min(79, cBufInfoLoc%dwMaximumWindowSize%X - 1)
  srWindowLoc%bottom = min(120, cBufInfoLoc%dwMaximumWindowSize%Y - 1)
  bool_result = SetConsoleWindowInfo(output_handle, TRUE, srWindowLoc)
  if (bool_result == 0) then
    print "(i0)", GetLastError()
    error stop 'SetConsoleWindowInfo failed'
  end if
end program set_window

 

0 Compliments
jirina
Nouveau contributeur I
2 229 Visites

Thank you, Andrew and Ian, for your valuable inputs. It is sufficient for me now to be able to change the console window size, without changing its position. I adjusted my code based on Ian's kind example and it works now; the problem was that I did not use

cBufInfoLoc%dwMaximumWindowSize

in my code. So, if my console window was positioned in such a way that it would not fit the screen after resizing, SetConsoleWindowInfo returned 0 and I concluded it does not work. After adding the maximum window size, everything works flawlessly.

Also, GetLastError can be used after I reviewed and optimized using ifport and ifwin by applying the ONLY feature of USE.

Thanks a lot once more!

0 Compliments
Répondre