Been having a lot of fun with DirectX recently. I've got a slight problem here though, about autoredraw. DirectX draws time after time, making it the best to leave autoredraw false. My problem is when i show a message box. It pops up and the game loop stops because it's modal. When it appears a rectangle immediately appears on you drawing window. Then if you move it around even more will go to the form's/picturebox's backcolor because autoredraw is set to false. This makes it look ugly, and cheap so i'd like to take it out. I tried setting autoredraw to true and then show the msgbox but it didn't work.
Msgbox's I believe halt all events in the particular program. Not really good to use in DirectX apps. Infact non of them do! So what you need to do is probably create your own DirectX style by creating a box, adding some text, and create your own button that is clickable. I did something like that over in my BossKillers game. But yeah definitely keep your autoredraw the false cause DX does it for you.
That's okayish and i'll do that if i have to but isn't there a way to get the picture? In my program vb's msgbox fits the bill perfectly. Another place where i'm killed on this is when i show a common dialog box. A msgbox can be drawn but a common dialog box is much more complicated and also i want the system by system capability of the cdb. I know that in your game a custom drawn msgbox works alright but this isn't a game, it's a very graphical water drainage editor. There are endless problems with autoredraw off, msgbox, cdb, modal forms, and the whole lot. Hopefully there's got to be a way to preserve the screen.
You can actually use VB's common dialog box in DX apps and not have problems. I did that with my map editor. No halts or graphical problems or nothing.
No? By saying no graphical problems do you mean that you can move the dialog box over the form and it won't mess it up? I solved part of the problem by calling the draw event in the form's paint. That fixes modal forms at least. I think that maybe the reason why cdbs don't mess it up for you is because of your os. I noticed on vista that a form autoredraws by default when it doesn't have focus whereas in xp the paint event will fire. Actually i just tried you map editor and it's just the same as msgboxes, it must be a difference with 7. Isn't there some way of directx communicating with the outside like writing an image file? If you could do that then it would be simple. Save a jpg with DX, load it into a picturebox and then your screen will be preserved.
Oooo I see now. It does mess it up. I'm using Windows 7 Pro 64 bit. But I wouldn't worry too much about that. Like in my map editor, once you load what you need to load, its back to normal. But if you are really really worried about it still, the best you can do is create your own dialog box. It's tricky but it shouldn't be a problem if you are able to work with files through code. You'll need an Origin File Path which generally should start where your application is at. Other programs tend to use Documents as the origin. Then within that folder you load all the folders that exist and put em into a list. Then you load all the files that exist and put em into a list. Once you have all the information you display them through directX into your window you created showing all the folders. With files you generally want to show only the files that are .jpgs or whatever pic formats you want and even need the option to show all files. The folders displayed in itself should be buttons so the user can go through the harddrive. If ya need help I might be able to help ya do this.
Ok, so i'm just wondering this now. Is there a way to save the directx screen to an image file? I'd think that dx would have something to accomplish that.
Wow! That looks perfect. I've got some strange errors though. When i try the snapshot sub I get the error "variable not defined" because of "Direct3DX." I tried the other dx variables in the project but none of them had "SaveSurfactToFile". When i tried take_snapshot, "DirectInput_Key_State" is a "sub or function not defined". This is especially weird as i would think that it would be in the dx library. Thanks for these subs! My plan for using them is when i do a msgbox or something to take a snapshot, load it into a vb picturebox and then there would be no more uglyness.
Sorry, although i'm able to use the direct input now but i'm still getting the error on the D3DX8 variable, it isn't being set up. Could you just post a form or the entire form code? That would be the easiest as then there wouldn't be a mix up in variable names or the complete lack of certain variables.
Whoops forgot you gotta initialize Direct3DX as well
Code:
Set Direct3DX = New D3DX8
Heres an example program of it in action:
[EDIT] I found that holding the print screen key or whatever key will use will sometimes end up taking multiple snapshots.
To handle this just use a boolean flag. If the keys held down its true, then the snapshot will only be taken once even when
keys held. I edited the program to do this:
vb Code:
Option Explicit
Private Const COLOR_DEPTH_16_BIT As Long = D3DFMT_R5G6B5
Private Const COLOR_DEPTH_24_BIT As Long = D3DFMT_A8R8G8B8
Private Const COLOR_DEPTH_32_BIT As Long = D3DFMT_X8R8G8B8
Private DX As DirectX8 'The master DirectX object.
Private Direct3D As Direct3D8 'Controls all things 3D.
Private Direct3D_Device As Direct3DDevice8 'Represents the hardware rendering.
Private Direct3DX As D3DX8
Private Direct_Input As DirectInput8
Private Keyboard_Device As DirectInputDevice8
Private Keyboard_State As DIKEYBOARDSTATE
Private Fullscreen_Enabled As Boolean 'Helps determine whether it's fullscreen mode.
Private Running As Boolean 'Helps determine whether the main game loop is running.
Private Snapshot_Number As Long
Private Snapshot_Flag as Boolean
Private Sub DirectX_Initialize()
Dim Display_Mode As D3DDISPLAYMODE 'Display mode desciption.
Dim Direct3D_Window As D3DPRESENT_PARAMETERS 'Backbuffer and viewport description.
Set DX = New DirectX8 'Creates the DirectX object.
Set Direct3D = DX.Direct3DCreate() 'Creates the Direct3D object using the DirectX object.
Set Direct3DX = New D3DX8
If Fullscreen_Enabled = True Then
'Now that we are working with fullscreen mode, we must set up the
'screen resolution to switch to, rather than use the default screen
'resolution.
Display_Mode.Width = 800
Display_Mode.Height = 600
Display_Mode.Format = COLOR_DEPTH_16_BIT
Direct3D_Window.Windowed = False 'The app will be in fullscreen mode.
Direct3D_Window.BackBufferCount = 1 '1 backbuffer only
Direct3D_Window.BackBufferWidth = Display_Mode.Width 'Match the backbuffer width with the display width
Direct3D_Window.BackBufferHeight = Display_Mode.Height 'Match the backbuffer height with the display height
Direct3D_Window.hDeviceWindow = frmMain.hWnd 'Use frmMain as the device window.
Else
Direct3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, Display_Mode 'Use the current display mode that you
'are already on. Incase you are confused, I'm
'talking about your current screen resolution. ;)
Direct3D_Window.Windowed = True 'The app will be in windowed mode.
End If
Direct3D_Window.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC 'Refresh when the monitor does.
Direct3D_Window.BackBufferFormat = Display_Mode.Format 'Sets the format that was retrieved into the backbuffer.
'Creates the rendering device with some useful info, along with the info
'we've already setup for Direct3D_Window.
Set Direct3D_Device = Direct3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, frmMain.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, Direct3D_Window)
End Sub
Private Sub DirectInput_Initialize_Keyboard(Window As Form)
'Use in Form_Load to initialize DirectInput for Keyboard
Set Direct_Input = DX.DirectInputCreate
Set Keyboard_Device = Direct_Input.CreateDevice("GUID_SysKeyboard")
It's not really. Unless you plan on taking 1000's upon 1000's of snapshots, then it would cause you'd then have to wait until it reaches that number. To speed it up you could use random numbers or hex, or whatever you'd like.
Also if you know anything about 2D clipping or are able to decipher krtxmrtz's 2D clipping program and splice it into mine (link included), I'm having issues doing that over in the 2D Polygon Clipping (Scissoring) thread. I know I know, I'm desperate
Hmmmmm. Something's wrong then, when i tried it it took ages. I put this in to take a screenshot:
Code:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyF1 Then
Dim StartTime: StartTime = Timer
Snapshot App.Path & "screenshot.jpg"
MsgBox Timer - StartTime
End If
End Sub
Just to make it easy for you this is my entire form code now:
vb Code:
Option Explicit
Private Const COLOR_DEPTH_16_BIT As Long = D3DFMT_R5G6B5
Private Const COLOR_DEPTH_24_BIT As Long = D3DFMT_A8R8G8B8
Private Const COLOR_DEPTH_32_BIT As Long = D3DFMT_X8R8G8B8
Private DX As DirectX8 'The master DirectX object.
Private Direct3D As Direct3D8 'Controls all things 3D.
Private Direct3D_Device As Direct3DDevice8 'Represents the hardware rendering.
Private Direct3DX As D3DX8
Private Direct_Input As DirectInput8
Private Keyboard_Device As DirectInputDevice8
Private Keyboard_State As DIKEYBOARDSTATE
Private Fullscreen_Enabled As Boolean 'Helps determine whether it's fullscreen mode.
Private Running As Boolean 'Helps determine whether the main game loop is running.
Private Snapshot_Number As Long
Private Snapshot_Flag As Boolean
Private Sub DirectX_Initialize()
Dim Display_Mode As D3DDISPLAYMODE 'Display mode desciption.
Dim Direct3D_Window As D3DPRESENT_PARAMETERS 'Backbuffer and viewport description.
Set DX = New DirectX8 'Creates the DirectX object.
Set Direct3D = DX.Direct3DCreate() 'Creates the Direct3D object using the DirectX object.
Set Direct3DX = New D3DX8
If Fullscreen_Enabled = True Then
'Now that we are working with fullscreen mode, we must set up the
'screen resolution to switch to, rather than use the default screen
'resolution.
Display_Mode.Width = 800
Display_Mode.Height = 600
Display_Mode.Format = COLOR_DEPTH_16_BIT
Direct3D_Window.Windowed = False 'The app will be in fullscreen mode.
Direct3D_Window.BackBufferCount = 1 '1 backbuffer only
Direct3D_Window.BackBufferWidth = Display_Mode.Width 'Match the backbuffer width with the display width
Direct3D_Window.BackBufferHeight = Display_Mode.Height 'Match the backbuffer height with the display height
Direct3D_Window.hDeviceWindow = frmMain.hWnd 'Use frmMain as the device window.
Else
Direct3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, Display_Mode 'Use the current display mode that you
'are already on. Incase you are confused, I'm
'talking about your current screen resolution. ;)
Direct3D_Window.Windowed = True 'The app will be in windowed mode.
End If
Direct3D_Window.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC 'Refresh when the monitor does.
Direct3D_Window.BackBufferFormat = Display_Mode.Format 'Sets the format that was retrieved into the backbuffer.
'Creates the rendering device with some useful info, along with the info
'we've already setup for Direct3D_Window.
Set Direct3D_Device = Direct3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, frmMain.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, Direct3D_Window)
End Sub
Private Sub DirectInput_Initialize_Keyboard(Window As Form)
'Use in Form_Load to initialize DirectInput for Keyboard
Set Direct_Input = DX.DirectInputCreate
Set Keyboard_Device = Direct_Input.CreateDevice("GUID_SysKeyboard")
If DirectInput_Key_State(DIK_ESCAPE) Then 'If the user presses the Esc key...
Shut_Down
End If
DoEvents 'Allow events to happen so the program doesn't lock up.
'Found out the hardway that it must be at the end of
'the loop if you plan to exit out of the program
'properly without using End
Loop
End Sub
Private Sub Main()
'This event will fire before the form has completely loaded
If MsgBox("Click Yes to go to full screen (Recommended)", vbQuestion Or vbYesNo, "Options") = vbYes Then Fullscreen_Enabled = True
Me.Show
frmMain.Caption = "DirectX Tutorial"
DirectX_Initialize
DirectInput_Initialize_Keyboard frmMain
Running = True 'Initializations all set. It's now ok to activate the game loop.
Game_Loop
End Sub
Private Sub Shut_Down()
Running = False 'Helps the program bail out of the game loop.
'Unload all of the DirectX objects
Set Direct_Input = Nothing
Set Direct3D_Device = Nothing
Set Direct3D = Nothing
Set DX = Nothing
Unload Me 'Unload the form
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyF1 Then
Dim StartTime: StartTime = Timer
Snapshot App.Path & "screenshot.jpg"
MsgBox Timer - StartTime
End If
End Sub
Private Sub Form_Load()
Main
End Sub
Private Sub Form_Unload(Cancel As Integer)
Shut_Down
End Sub
For some reason when i take a screenshot it spends 1.3 seconds doing so. The part where it spends all the time is on this line in the screenshot sub: "Direct3D_Device.GetFrontBuffer Surface"
As for the clipping i'm sorry that i can't help you . When it comes to directx you're the boss, i would have no idea how to do that.
Ever play World of Warcraft? Their screenshot button has a noticable pause too. That's cause Windows is busy creating the file. It affects all programs running really. It's just something you gotta deal with.
Edit: Update. I just found a fast way to take a screenshot, which works entirely in the program. reacen posted it here:http://www.vbforums.com/showthread.p...form+menu+fade. This is plenty fast and now i can preserve my screen by doing this (by the way in the program i'm drawing dx in a picturebox).
Code:
Private Sub LockScreen()
Me.Picture = modSc.CaptureWindow(Me.hWnd, False, 4, 30, (Me.Width / 15) - 8, (Me.Height / 15) - 34)
picWorld.Visible = False
End Sub
Private Sub UnLockScreen()
picWorld.Visible = True
Draw
Me.Picture = Nothing
End Sub
So i lock the screen, show the msgbox or cdb and then unlock the screen. This is totally resolved!
Last edited by cheesebrother; Dec 16th, 2011 at 02:35 PM.