用API函数改写屏幕分辨率的问题?

紧凑型程序员 2003-07-05 12:55:20
模块定义如下:
Private Declare Function Lstrcpy Lib "kernel32" Alias "lstrcpyA"_ (lpString1 As Any, lpString2 As Any) As Long
Private Declare Function ChangeDisplaySettings Lib "User32"_
Alias "ChangeDisplaySettingsA" (ByVal lpDevMode As Long, ByVal dwflags_ As Long) As Long
Public Declare Function SystemParametersInfo Lib "User32"_ Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As_ Long, ByVal lpvParam As Any, ByVal fuWinIni As Long) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public apiRECT As RECT
Public Const SPI_GETWORKAREA = 48
Const CCHDEVICENAME = 32
Const CCHFORMNAME = 32
Private Type DEVMODE
dmDeviceName As String * CCHDEVICENAME
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 * CCHFORMNAME
dmUnusedPadding As Integer
dmBitsPerPel As Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
' 动态改变屏幕设置的函数
Public Function SetDisplayMode(Width As Integer, Height As Integer,_ Color As Integer) As Long
Const DM_PELSWIDTH = &H80000
Const DM_PELSHEIGHT = &H100000
Const DM_BITSPERPEL = &H40000
Dim NewDevMode As DEVMODE
Dim pDevmode As Long
With NewDevMode
.dmSize = 122
If Color = -1 Then
.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT
Else
.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT Or DM_BITSPERPEL
End If
.dmPelsWidth = Width
.dmPelsHeight = Height
If Color <> -1 Then
.dmBitsPerPel = Color
End If
End With
pDevmode = Lstrcpy(NewDevMode, NewDevMode)
SetDisplayMode = ChangeDisplaySettings(pDevmode, 0)
End Function

窗体载入时语句:
'得到屏幕当前分辨率
SystemParametersInfo SPI_GETWORKAREA, vbNull, VarPtr(apiRECT), 0
'将屏幕当前分辨率保存于 Screen.txt
Open App.Path + "\" + "Screen.txt" For Output As #1
Write #1, apiRECT.Right
Close #1
'将屏幕分辨率改为800×600
SetDisplayMode 800, 600, 16

但此种方法并没有改变1024*768的分辨率为800*600的分辨率,在单步执行时
SetDisplayMode 函数的返回值为-2,是不是函数执行失败啊!哪我应该怎么解决呢?
谢谢高人指点啊?
...全文
21 点赞 收藏 3
写回复
3 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
gpo2002 2003-07-05
To a new form, add a top-level menu item, and name it "mnuDisplayModes". Add a single submenu item under this, and name this menu item "mnuModes". Set it's index to 0 to create the necessary menu array. Add a command button (Command1), along with the following code:

--------------------------------------------------------------------------------

Option Explicit

'vars set in load
Dim currHRes As Long
Dim currVRes As Long
Dim currBPP As Long

'var set in mnuModes
Dim currMenuItem As Long

'array of valid resolutions & colour depths
Dim resArray() As Long

'const for the members of the array
'i.e. resArray(resWidth, Index) = 1024
'i.e. resArray(resHeight, Index) = 768
'i.e. resArray(resDepth, Index)= 16 'Bits per pixel
Const resWidth = 1
Const resHeight = 2
Const resDepth = 3


Private Sub Form_Load()

'retrieves the current screen resolution for
'later comparison against DEVMODE values in
'CompareSettings.
currHRes = GetDeviceCaps(hdc, HORZRES)
currVRes = GetDeviceCaps(hdc, VERTRES)
currBPP = GetDeviceCaps(hdc, BITSPIXEL)

Dim maxItems As Long
InitializeDisplayMenu maxItems
FinalizeDisplayMenu maxItems

End Sub


Private Sub FinalizeDisplayMenu(maxItems As Long)

'This adds a separator and a final menu item,
'providing the ability to open the control panel
'display settings page from the app.
If maxItems > 0 Then

Dim hMenu As Long
Dim r As Long

'add the separator
maxItems = maxItems + 1
Load mnuModes(maxItems)
mnuModes(maxItems).Caption = "-"

'add the final item
maxItems = maxItems + 1
Load mnuModes(maxItems)
mnuModes(maxItems).Caption = "Show Display Settings"

'finally, bold the newly-added menuitem
hMenu = GetSubMenu(GetMenu(Me.hWnd), 0)
Call SetMenuDefaultItem(hMenu, maxItems - 1, True)

End If

End Sub


Private Sub InitializeDisplayMenu(maxItems As Long)

Dim DM As DEVMODE
Dim dMode As Long

'36 should be enough to hold your settings.
'It's trimmed back at the end of this routine.
ReDim resArray(1 To 3, 0 To 35)

'set the DEVMODE flags and structure size
DM.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT Or DM_BITSPERPEL
DM.dmSize = LenB(DM)

'The first mode is 0
dMode = 0

'call the API to retrieve the values for the
'specified dMode
Do While EnumDisplaySettings(0&, dMode, DM) > 0

'if the BitsPerPixel is greater than 4
'(16 colours), then add the item to a menu
If DM.dmBitsPerPel >= 4 Then
Call MenuAdd(DM, resArray(), maxItems)
End If

'increment and call again. Continue until
'EnumDisplaySettings returns 0 (no more settings)
dMode = dMode + 1

Loop

'trim back the resArray to fit the number of actual entries.
ReDim Preserve resArray(1 To 3, 0 To maxItems)

End Sub


Private Function CompareSettings(DM As DEVMODE) As Long

'compares the current screen resolution with
'the current DEVMODE values. Returns TRUE if
'the horizontal and vertical resolutions, and
'the bits per pixel colour depth, are the same.
CompareSettings = (DM.dmBitsPerPel = currBPP) And _
DM.dmPelsHeight = currVRes And _
DM.dmPelsWidth = currHRes

End Function


Private Sub MenuAdd(DM As DEVMODE, resArray() As Long, mnuCount As Long)

Dim mType As String

'used to determine when the colour depth has
'changed, so we can add a separator to the menu.
Static lastBitsPerPel As Long

'select the appropriate text string based on
'the colour depth
Select Case DM.dmBitsPerPel
Case 4: mType = "16 Color"
Case 8: mType = "256 Color"
Case 16: mType = "High Color"
Case 24, 32: mType = "True Color"
End Select

'if this is the first item, we can't load the menu
'array item, and it will not require a separator.
If mnuCount > 0 Then

'load a new menu item to the array
Load mnuModes(mnuCount)

'determine if the colour depth has changed. If so,
'make the caption a separator, and load a new item
'to hold the item.
If lastBitsPerPel <> DM.dmBitsPerPel Then

mnuModes(mnuCount).Caption = "-"
mnuCount = mnuCount + 1
Load mnuModes(mnuCount)

End If
End If

'create the menu caption
mnuModes(mnuCount).Caption = DM.dmPelsWidth & "x" & _
DM.dmPelsHeight & " [" & _
DM.dmBitsPerPel & " bit " & _
mType & "]"

'see if this is the current resolution,
'and if so, check the menu item
mnuModes(mnuCount).Checked = CompareSettings(DM)
If mnuModes(mnuCount).Checked Then currMenuItem = mnuCount

resArray(resWidth, mnuCount) = DM.dmPelsWidth
resArray(resHeight, mnuCount) = DM.dmPelsHeight
resArray(resDepth, mnuCount) = DM.dmBitsPerPel

'save the current DEVMODE value for depth
'and increment the menu item count, ready for
'the next call
lastBitsPerPel = DM.dmBitsPerPel
mnuCount = mnuCount + 1

End Sub


Private Sub Command1_Click()

Dim maxItems As Long

InitializeDisplayMenu maxItems
Command1.Enabled = False

FinalizeDisplayMenu maxItems

End Sub


Private Sub mnuModes_Click(Index As Integer)

Dim DM As DEVMODE

Select Case Index

Case mnuModes.Count

'show the display control panel
Call Shell("rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,3", 1)

Case Else

'change the current resolution, no prompting
'BE CAREFUL .. you could set your system to a
'setting which renders the display difficult to read.

With DM

.dmPelsWidth = resArray(resWidth, Index)
.dmPelsHeight = resArray(resHeight, Index)
.dmBitsPerPel = resArray(resDepth, Index)
.dmFields = DM_PELSWIDTH Or DM_PELSHEIGHT Or DM_BITSPERPEL
.dmSize = LenB(DM)
End With

If ChangeDisplaySettings(DM, CDS_FORCE) <> 0 Then

MsgBox "Error! Perhaps your hardware is not up to the task?"

End If

'indicate the current menu selection
mnuModes(currMenuItem).Checked = False
mnuModes(Index).Checked = True
currMenuItem = Index

End Select

End Sub
'--end block--'

回复
gpo2002 2003-07-05
Place the following code into the general declarations area of a bas module:

--------------------------------------------------------------------------------

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2002 VBnet, Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you can not publish
' or reproduce this code on any web site,
' on any online service, or distribute on
' any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Declare Function EnumDisplaySettings Lib "user32" _
Alias "EnumDisplaySettingsA" _
(ByVal lpszDeviceName As Long, _
ByVal iModeNum As Long, _
lpDevMode As Any) As Boolean

Public Declare Function GetDeviceCaps Lib "gdi32" _
(ByVal hdc As Long, _
ByVal nIndex As Long) As Long

Public Declare Function ChangeDisplaySettings Lib "user32" _
Alias "ChangeDisplaySettingsA" _
(lpDevMode As Any, _
ByVal dwflags As Long) As Long

Public Declare Function SetMenuDefaultItem Lib "user32" _
(ByVal hMenu As Long, _
ByVal uItem As Long, _
ByVal fByPos As Long) As Long

Public Declare Function GetMenu Lib "user32" _
(ByVal hWnd As Long) As Long

Public Declare Function GetSubMenu Lib "user32" _
(ByVal hMenu As Long, _
ByVal nPos As Long) As Long

Public Const LOGPIXELSX As Long = 88
Public Const LOGPIXELSY As Long = 90
Public Const BITSPIXEL As Long = 12
Public Const HORZRES As Long = 8
Public Const VERTRES As Long = 10

Public Const CCDEVICENAME As Long = 32
Public Const CCFORMNAME As Long = 32

Public Const DM_GRAYSCALE As Long = &H1
Public Const DM_INTERLACED As Long = &H2

Public Const DM_BITSPERPEL As Long = &H40000
Public Const DM_PELSWIDTH As Long = &H80000
Public Const DM_PELSHEIGHT As Long = &H100000
Public Const DM_DISPLAYFLAGS As Long = &H200000

Public Const CDS_UPDATEREGISTRY As Long = &H1
Public Const CDS_TEST As Long = &H2
Public Const CDS_FULLSCREEN As Long = &H4
Public Const CDS_GLOBAL As Long = &H8
Public Const CDS_SET_PRIMARY As Long = &H10
Public Const CDS_NORESET As Long = &H10000000
Public Const CDS_SETRECT As Long = &H20000000
Public Const CDS_RESET As Long = &H40000000
Public Const CDS_FORCE As Long = &H80000000

'Return values for ChangeDisplaySettings
'Public Const DISP_CHANGE_SUCCESSFUL = 0
'Public Const DISP_CHANGE_RESTART = 1
'Public Const DISP_CHANGE_FAILED = -1
'Public Const DISP_CHANGE_BADMODE = -2
'Public Const DISP_CHANGE_NOTUPDATED = -3
'Public Const DISP_CHANGE_BADFLAGS = -4
'Public Const DISP_CHANGE_BADPARAM = -5

Public 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
End Type
'--end block--'

回复
rainstormmaster 2003-07-05
在我这里,执行正常(win98)。请确认你的显卡是否支持800*600,16位色的分辨率
回复
相关推荐
发帖
API
创建于2007-09-28

1466

社区成员

VB API
申请成为版主
帖子事件
创建了帖子
2003-07-05 12:55
社区公告
暂无公告