LittleTim
asked on
Modifying the screen resolution
Hello all,
I'm trying to modify the screen resolution with Windows API and VB coding (VBA for MS Access).
The fragment of code goes like this:
Private Declare Function EnumDisplaySettings Lib "user32" _
Alias "EnumDisplaySettingsA" _
(ByVal lpszDeviceName As Long, _
ByVal iModeNum As Long, _
lpDevMode As Any) As Boolean
Private Declare Function ChangeDisplaySettings Lib "user32" _
Alias "ChangeDisplaySettingsA" _
(lpDevMode As Any, _
ByVal dwflags As Long) As Long
Public Sub ChangeRes(iWidth As Single, iHeight As Single)
Dim blnWorked As Boolean
Dim i As Long
Dim DevM As DEVMODE
i = 0
Do
blnWorked = EnumDisplaySettings(0&, i, DevM)
i = i + 1
Loop Until (blnWorked = False)
With DevM
.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
.dmPelsWidth = iWidth
.dmPelsHeight = iHeight
End With
Call ChangeDisplaySettings(DevM , 0)
End Sub
The code works wonders with modifying the screen resolution (change from 800x600 to 1280x1024), however, when the screen res changes, the start menu bar from Windows XP moves up the screen as well. It doesn't seem to want to stay at the bottom of the screen.
The screen looks odd with the start bar in the middle of the screen. I was just wondering whether there's any fixes to this? i.e screen refresh?
Many thanks for any pointers to the right direction!
I'm trying to modify the screen resolution with Windows API and VB coding (VBA for MS Access).
The fragment of code goes like this:
Private Declare Function EnumDisplaySettings Lib "user32" _
Alias "EnumDisplaySettingsA" _
(ByVal lpszDeviceName As Long, _
ByVal iModeNum As Long, _
lpDevMode As Any) As Boolean
Private Declare Function ChangeDisplaySettings Lib "user32" _
Alias "ChangeDisplaySettingsA" _
(lpDevMode As Any, _
ByVal dwflags As Long) As Long
Public Sub ChangeRes(iWidth As Single, iHeight As Single)
Dim blnWorked As Boolean
Dim i As Long
Dim DevM As DEVMODE
i = 0
Do
blnWorked = EnumDisplaySettings(0&, i, DevM)
i = i + 1
Loop Until (blnWorked = False)
With DevM
.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
.dmPelsWidth = iWidth
.dmPelsHeight = iHeight
End With
Call ChangeDisplaySettings(DevM
End Sub
The code works wonders with modifying the screen resolution (change from 800x600 to 1280x1024), however, when the screen res changes, the start menu bar from Windows XP moves up the screen as well. It doesn't seem to want to stay at the bottom of the screen.
The screen looks odd with the start bar in the middle of the screen. I was just wondering whether there's any fixes to this? i.e screen refresh?
Many thanks for any pointers to the right direction!
ASKER
Thanks Jaime,
Unfortunately, changing the refresh frequency did not fix my problem - I've tried all the frequencies that my LCD takes....
:<
Unfortunately, changing the refresh frequency did not fix my problem - I've tried all the frequencies that my LCD takes....
:<
This works for me on XP:
Const CCDEVICENAME = 32
Const CCFORMNAME = 32
Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Const CDS_TEST = &H4
Private Type DISPLAY_DEVICE
cb As Long
DeviceName As String * 32
DeviceString As String * 128
StateFlags As Long
DeviceID As String * 128
DeviceKey As String * 128
End Type
Private Type DEVMODE
dmDeviceName As String * CCDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
dmICMMethod As Long 'NT 4.0
dmICMIntent As Long 'NT 4.0
dmMediaType As Long 'NT 4.0
dmDitherType As Long 'NT 4.0
dmReserved1 As Long 'NT 4.0
dmReserved2 As Long 'NT 4.0
dmPanningWidth As Long 'Win2000
dmPanningHeight As Long 'Win2000
End Type
Private Declare Function ChangeDisplaySettingsEx Lib "user32" Alias "ChangeDisplaySettingsExA" (lpszDeviceName As Any, lpDevMode As Any, ByVal hWnd As Long, ByVal dwFlags As Long, lParam As Any) As Long
Private Declare Function EnumDisplayDevices Lib "user32" Alias "EnumDisplayDevicesA" (Unused As Any, ByVal iDevNum As Long, lpDisplayDevice As DISPLAY_DEVICE, ByVal dwFlags As Long) As Boolean
Dim OldX As Long, OldY As Long, T As Long
Private Sub Form_Load()
'KPD-Team 2000
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim DD As DISPLAY_DEVICE, DevM As DEVMODE
DD.cb = Len(DD)
OldX = Screen.Width / Screen.TwipsPerPixelX
OldY = Screen.Height / Screen.TwipsPerPixelY
'First retieve some display info
If EnumDisplayDevices(ByVal 0&, 0, DD, ByVal 0&) Then
'and show it
Me.AutoRedraw = True
Me.Print "Device String:" + Left$(DD.DeviceString, InStr(1, DD.DeviceString, Chr$(0)) - 1)
Me.Print "Device Name:" + Left$(DD.DeviceName, InStr(1, DD.DeviceName, Chr$(0)) - 1)
Me.Print "Device Key:" + Left$(DD.DeviceKey, InStr(1, DD.DeviceKey, Chr$(0)) - 1)
Me.Print "Device ID:" + Left$(DD.DeviceID, InStr(1, DD.DeviceID, Chr$(0)) - 1)
Else
Me.Print "Error while retrieving Display Information"
End If
DevM.dmSize = Len(DevM)
'we want to change the horizontal and the vertical resolution
DevM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
DevM.dmPelsWidth = 800
DevM.dmPelsHeight = 600
'change the display settings
Call ChangeDisplaySettingsEx(By Val 0&, DevM, ByVal 0&, CDS_TEST, ByVal 0&)
T = Timer
Do: DoEvents: Loop Until Timer > T + 5
DevM.dmPelsWidth = OldX
DevM.dmPelsHeight = OldY
'change the display settings back to the old settings
Call ChangeDisplaySettingsEx(By Val 0&, DevM, ByVal 0&, CDS_TEST, ByVal 0&)
End Sub
Const CCDEVICENAME = 32
Const CCFORMNAME = 32
Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Const CDS_TEST = &H4
Private Type DISPLAY_DEVICE
cb As Long
DeviceName As String * 32
DeviceString As String * 128
StateFlags As Long
DeviceID As String * 128
DeviceKey As String * 128
End Type
Private Type DEVMODE
dmDeviceName As String * CCDEVICENAME
dmSpecVersion As Integer
dmDriverVersion As Integer
dmSize As Integer
dmDriverExtra As Integer
dmFields As Long
dmOrientation As Integer
dmPaperSize As Integer
dmPaperLength As Integer
dmPaperWidth As Integer
dmScale As Integer
dmCopies As Integer
dmDefaultSource As Integer
dmPrintQuality As Integer
dmColor As Integer
dmDuplex As Integer
dmYResolution As Integer
dmTTOption As Integer
dmCollate As Integer
dmFormName As String * CCFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
dmICMMethod As Long 'NT 4.0
dmICMIntent As Long 'NT 4.0
dmMediaType As Long 'NT 4.0
dmDitherType As Long 'NT 4.0
dmReserved1 As Long 'NT 4.0
dmReserved2 As Long 'NT 4.0
dmPanningWidth As Long 'Win2000
dmPanningHeight As Long 'Win2000
End Type
Private Declare Function ChangeDisplaySettingsEx Lib "user32" Alias "ChangeDisplaySettingsExA"
Private Declare Function EnumDisplayDevices Lib "user32" Alias "EnumDisplayDevicesA" (Unused As Any, ByVal iDevNum As Long, lpDisplayDevice As DISPLAY_DEVICE, ByVal dwFlags As Long) As Boolean
Dim OldX As Long, OldY As Long, T As Long
Private Sub Form_Load()
'KPD-Team 2000
'URL: http://www.allapi.net/
'E-Mail: KPDTeam@Allapi.net
Dim DD As DISPLAY_DEVICE, DevM As DEVMODE
DD.cb = Len(DD)
OldX = Screen.Width / Screen.TwipsPerPixelX
OldY = Screen.Height / Screen.TwipsPerPixelY
'First retieve some display info
If EnumDisplayDevices(ByVal 0&, 0, DD, ByVal 0&) Then
'and show it
Me.AutoRedraw = True
Me.Print "Device String:" + Left$(DD.DeviceString, InStr(1, DD.DeviceString, Chr$(0)) - 1)
Me.Print "Device Name:" + Left$(DD.DeviceName, InStr(1, DD.DeviceName, Chr$(0)) - 1)
Me.Print "Device Key:" + Left$(DD.DeviceKey, InStr(1, DD.DeviceKey, Chr$(0)) - 1)
Me.Print "Device ID:" + Left$(DD.DeviceID, InStr(1, DD.DeviceID, Chr$(0)) - 1)
Else
Me.Print "Error while retrieving Display Information"
End If
DevM.dmSize = Len(DevM)
'we want to change the horizontal and the vertical resolution
DevM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
DevM.dmPelsWidth = 800
DevM.dmPelsHeight = 600
'change the display settings
Call ChangeDisplaySettingsEx(By
T = Timer
Do: DoEvents: Loop Until Timer > T + 5
DevM.dmPelsWidth = OldX
DevM.dmPelsHeight = OldY
'change the display settings back to the old settings
Call ChangeDisplaySettingsEx(By
End Sub
Are you sure your taskbar is appearing in the middle of the screen? or your screen has been reduced in size. Also make a simple test, press Ctrl-Alt-Del, kill the "explorer.exe" process in the "Processes" tab, and create a new "explorer.exe" task in the "Applications", button "NewTask...".
ASKER
Hi,
Many thanks for the replies....I've tried the solution by mladenovicz (without the Me.Autoredraw, as VBA does not support it), yet my taskbar centres with accordance to an increase to the resolution. If I decrease the resolution, it naturally returns to the normal place (bottom of the screen). Is it because I'm using an LCD that this problem is occurring?
I have also tried Jame's suggestion of killing the task bar, and recreating it - It redraws perfectly on the bottom of the screen.
Many thanks for the replies....I've tried the solution by mladenovicz (without the Me.Autoredraw, as VBA does not support it), yet my taskbar centres with accordance to an increase to the resolution. If I decrease the resolution, it naturally returns to the normal place (bottom of the screen). Is it because I'm using an LCD that this problem is occurring?
I have also tried Jame's suggestion of killing the task bar, and recreating it - It redraws perfectly on the bottom of the screen.
> Is it because I'm using an LCD that this problem is occurring?
I don't think so, but the best way is to try with a monitor.
About the killing test. Maybe you can force the desktop to refresh once after changing resolution.
Reviewing some code snippets I noticed you are starting with an "empty" DEVMODE structure, so you can try to do this:
Replace this line:
DevM.dmSize = Len(DevM)
with:
EnumDisplaySettings(0, 0, DevM)
I don't think so, but the best way is to try with a monitor.
About the killing test. Maybe you can force the desktop to refresh once after changing resolution.
Reviewing some code snippets I noticed you are starting with an "empty" DEVMODE structure, so you can try to do this:
Replace this line:
DevM.dmSize = Len(DevM)
with:
EnumDisplaySettings(0, 0, DevM)
ASKER
Hi Jaime,
Is it possible to programmically force a desktop resfresh? Within VBA, the code Me.Repaint doesn't do the refresh required for the desktop.
I was also thinking of killing the explorer.exe task, but I can't find its handle instance with:
intWindowHandle = FindWindow(0&, strCaptionTitle) 'where strCaptionTitle = "explorer"
If (intWindowHandle <> 0) Then
' *************** window found
intTaskHandle = GetWindowTask(intWindowHan dle)
intPostReturnValue = PostAppMessage(intTaskHand le, WM_QUIT, 0, 0&) 'Kill the instance.
and then calling the shell function: shell("explorer.exe", vbNormalFocus) to restart the instance.
The problem is that the findWindow API needs an active window for comparison. Also, if interent explorer is running, it naturally assumes that its the current window that we're trying to find....
Is it possible to retrieve the handle of the "explorer.exe" task only?
if not, how can I force a desktop to refresh itself through VB / VBA (I'm controlling the screen through Access
Many thanks.
Is it possible to programmically force a desktop resfresh? Within VBA, the code Me.Repaint doesn't do the refresh required for the desktop.
I was also thinking of killing the explorer.exe task, but I can't find its handle instance with:
intWindowHandle = FindWindow(0&, strCaptionTitle) 'where strCaptionTitle = "explorer"
If (intWindowHandle <> 0) Then
' *************** window found
intTaskHandle = GetWindowTask(intWindowHan
intPostReturnValue = PostAppMessage(intTaskHand
and then calling the shell function: shell("explorer.exe", vbNormalFocus) to restart the instance.
The problem is that the findWindow API needs an active window for comparison. Also, if interent explorer is running, it naturally assumes that its the current window that we're trying to find....
Is it possible to retrieve the handle of the "explorer.exe" task only?
if not, how can I force a desktop to refresh itself through VB / VBA (I'm controlling the screen through Access
Many thanks.
Take a look to this code, maybe you can simply reposition the taskbar properly:
http://vb-town.tripod.com/Tips/hidetaskbar.htm
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=47014&lngWId=1
http://vb-town.tripod.com/Tips/hidetaskbar.htm
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=47014&lngWId=1
ASKER
Thanks jaime for your patience....
I've tried the link http://vb-town.tripod.com/Tips/hidetaskbar.htm. It does indeed redraw the taskbar, except at the exact same location prior hiding it. (i.e, the x , y axis are the same at 0,0, and 0,0 seems to be at the centre.....)....
I note that
hwnd1 = FindWindow("Shell_traywnd" , "")
returns a hwd, which I tried killing with PostMessage (as per earlier), except an error 'overflow' is generated.
Anyway....I'll keep searching for now...
I've tried the link http://vb-town.tripod.com/Tips/hidetaskbar.htm. It does indeed redraw the taskbar, except at the exact same location prior hiding it. (i.e, the x , y axis are the same at 0,0, and 0,0 seems to be at the centre.....)....
I note that
hwnd1 = FindWindow("Shell_traywnd"
returns a hwd, which I tried killing with PostMessage (as per earlier), except an error 'overflow' is generated.
Anyway....I'll keep searching for now...
Let's go step by step:
SetWindowPos will allow you to reposition any window with the proper arguments.
try to reposition with:
Public Const SWP_NOSIZE = &H1
Call SetWindowPos(hwnd1, 0, 20, 20, 0, 0, SWP_NOSIZE)
This must move the taskbar to the 20,20 position of the screen (almost upper left corner)
PS. Notice that the taskbar is a window, not the explorer application
SetWindowPos will allow you to reposition any window with the proper arguments.
try to reposition with:
Public Const SWP_NOSIZE = &H1
Call SetWindowPos(hwnd1, 0, 20, 20, 0, 0, SWP_NOSIZE)
This must move the taskbar to the 20,20 position of the screen (almost upper left corner)
PS. Notice that the taskbar is a window, not the explorer application
ASKER
I don't know what exactly is happening....the code fragment:
Public Const SWP_NOSIZE = &H1
Call SetWindowPos(hwnd1, 0, 20, 20, 0, 0, SWP_NOSIZE)
does nothing at all. I am not too sure the reason as to why this is the case.
Public Const SWP_NOSIZE = &H1
Call SetWindowPos(hwnd1, 0, 20, 20, 0, 0, SWP_NOSIZE)
does nothing at all. I am not too sure the reason as to why this is the case.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
And more...
"Change display resolution in Windows XP"
http://www.vb-helper.com/howto_change_display_mode_xp.html
"Change display resolution in Windows XP"
http://www.vb-helper.com/howto_change_display_mode_xp.html
ASKER
Guys,
I'm very very grateful for the help you've all given. I would like to apologize, firstly for taking up you time, secondly, for giving you guys the run around!!! I didn't note until the last comment by nichia that my workstation at work was Windows 2000 as opposed to the XP development environment I was using when I was testing my code at home! Silly me, and again, apologies....
The problem was indeed inherent with Win 2000, and the resolution by nichia (Microsoft Knowledge base article) gave me a fix!
FYI, win 2000 requires the argument CDS_UPDATEREGISTRY (permanent write to the registry) to be passed into the changeDisplaySetting
i.e. ChangeDisplaySettings(DevM , CDS_UPDATEREGISTRY), otherwise the taskbar floats around...
However, CDS_UPDATEREGISTRY is not a windows variable, hence it needs to be declared as:
Const CDS_UPDATEREGISTRY = &H1
before hand.
Again, thanks guys.....you've been great!
I'm very very grateful for the help you've all given. I would like to apologize, firstly for taking up you time, secondly, for giving you guys the run around!!! I didn't note until the last comment by nichia that my workstation at work was Windows 2000 as opposed to the XP development environment I was using when I was testing my code at home! Silly me, and again, apologies....
The problem was indeed inherent with Win 2000, and the resolution by nichia (Microsoft Knowledge base article) gave me a fix!
FYI, win 2000 requires the argument CDS_UPDATEREGISTRY (permanent write to the registry) to be passed into the changeDisplaySetting
i.e. ChangeDisplaySettings(DevM
However, CDS_UPDATEREGISTRY is not a windows variable, hence it needs to be declared as:
Const CDS_UPDATEREGISTRY = &H1
before hand.
Again, thanks guys.....you've been great!
.dmFields = DM_DISPLAYFREQUENCY Or M_PELSWIDTH Or DM_PELSHEIGHT
.dmDisplayFrequency = 70 ' Try with different values