Learn how to a build a cloud-first strategyRegister Now


Modifying the screen resolution

Posted on 2004-08-22
Medium Priority
Last Modified: 2010-05-02
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
        blnWorked = EnumDisplaySettings(0&, i, DevM)
        i = i + 1
    Loop Until (blnWorked = False)
    With DevM
        .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!
Question by:LittleTim
  • 6
  • 6
  • 2
  • +1
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11866905
Maybe you need to specify a proper display frequency:

.dmDisplayFrequency = 70      ' Try with different values


Author Comment

ID: 11867268
Thanks Jaime,

   Unfortunately, changing the refresh frequency did not fix my problem - I've tried all the frequencies that my LCD takes....


Expert Comment

ID: 11868426
This works for me on XP:

Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Const CDS_TEST = &H4
    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
    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)
        Me.Print "Error while retrieving Display Information"
    End If
    DevM.dmSize = Len(DevM)
    'we want to change the horizontal and the vertical resolution
    DevM.dmPelsWidth = 800
    DevM.dmPelsHeight = 600
    'change the display settings
    Call ChangeDisplaySettingsEx(ByVal 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(ByVal 0&, DevM, ByVal 0&, CDS_TEST, ByVal 0&)
End Sub
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

LVL 55

Expert Comment

by:Jaime Olivares
ID: 11869754
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...".

Author Comment

ID: 11876469

   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.

LVL 55

Expert Comment

by:Jaime Olivares
ID: 11876613
> 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)

       EnumDisplaySettings(0, 0, DevM)

Author Comment

ID: 11876884
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(intWindowHandle)
        intPostReturnValue = PostAppMessage(intTaskHandle, 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.

LVL 55

Expert Comment

by:Jaime Olivares
ID: 11876941

Author Comment

ID: 11877063
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...

LVL 55

Expert Comment

by:Jaime Olivares
ID: 11877141
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

Author Comment

ID: 11877341
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.

LVL 55

Assisted Solution

by:Jaime Olivares
Jaime Olivares earned 600 total points
ID: 11877407
Maybe don't have put in a proper place, it will move the taskbar to an specific position (20,20) in this case. Use it with the same link you have tested, put it just after this line:

     Call SetWindowPos(hwnd1, 0, 0, 0, 0, 0, SWP_SHOWWINDOW)

Accepted Solution

nichia earned 400 total points
ID: 11877454
This info may be helpful:

"PRB: ChangeDisplaySettings Does Not Reposition Taskbar"


Expert Comment

ID: 11877479
And more...

"Change display resolution in Windows XP"


Author Comment

ID: 11877581

   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:

before hand.

Again, thanks guys.....you've been great!


Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Suggested Courses

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question