So, for my RGSS Addon, I decided they I should use the win32api to set pixels and that sort of stuff. So, I got the handle of device context, and I tried to set several pixels in the window, but the function keeps returning -1 (failure). There's probably something that I'm missing, but could someone help me figure this out.
My code:
def win32test
@find_window = Win32API.new("user32", "FindWindow", "LL", "L")
@set_pixel = Win32API.new("gdi32", "SetPixel", "PIIP", "I")
window = @find_window.call("RGSS Player", "Test")
color = 0x00FF0000
result = @set_pixel.call(window, 0, 0, color)
print result
end
As far as I know, RMXP runs using DirectDraw so the backbuffer is probably locked to DirectDraw only and you can't use GDI on the window. Have you looked up what the error code -1 means?
I suggest taking a look into BitBlt.
In the Win32API documentation, -1 means that the method failed. If it succeeds it returns the rgb value of the pixel (I think).
I would try to use BitBlt, but I don't know where I'd get the handle of device context for the source image. However, I'll just keep looking through the documentation for something useful.
Actually I just remembered. I think you're doing it wrong in the first code. The device context is not the same as the window handle. Does the documentation except a DWORD or a HWND? Because if it's a DWORD, it's likely that you are sending it the wrong parameter. You will probably have to call GetDC with the HWND that you get from FindWindow and this will be then the device context which you pass on to SetPixel. Don't forget to call ReleaseDC afterwards or the whole game may break.
Look up GetDC and ReleaseDC in the MSDN docs. If I remember right, GetDC takes the HWND parameter and returns the device context while ReleaseDC takes the device context as parameter and returns an error code or 0 on success.
Alright, so now it gets to the find window command and shuts down. All I added were the getDC and releaseDC commands, and now it dies on the find window command. Here's my new code.
def win32test
@find_window = Win32API.new("user32", "FindWindow", "PP", "P")
@set_pixel = Win32API.new("gdi32", "SetPixel", "PIIP", "I")
@get_dc = Win32API.new("user32", "GetDC","P","P")
@release_dc = Win32API.new("user32", "ReleaseDC","PP","P")
title = "Test"
window = @find_window.call("RGSS Player", title)
window2 = @get_dc.call(window)
@release_dc.call(window, window2)
color = 0x00FF0000
result = @set_pixel.call(window, 0, 0, color)
print result
end
You are supposed to release the DC after the SetPixel call.
I think that FindWindow crashes because you changed the return type from "L" to "P" which is incorrect as HWND is an "L".
The documentation also says that SetPixel should be using "LIIL" as parameters and "L" as return type. Both HDC and COLORREF are actually DWORDs which are designated as "L".
Same for GetDC. It should be "L", "L".
And ReleaseDC should be "LL", "I".
You used "P" everywhere. "P" means pointer. It is used for array data and char strings, not for "ints" and "longs".
Thank you so much Blizzard, now how do you make it stay on the screen. It shows for a few seconds, and then vanishes. I have it redraw it in the update event, but it doesn't do any good.
You actually have to redraw it each time after Graphics.update was called. Graphics.update clears the backbuffer and redraws the whole scene so your manual drawing is also removed. The only way how you could keep something on the screen is if you created a Sprite in RMXP's scripts, created and assigned a Bitmap to it and drew your stuff on that Bitmap. Obviously the sprite should have a high z coordinate to always appear over all the other sprites.
But how would you make Win32 make it part of the bitmap of the sprite. All I see are commands to draw on the window.
Quote from: Blizzard on May 20, 2012, 05:59:58 pm
You actually have to redraw it each time after Graphics.update was called. Graphics.update clears the backbuffer and redraws the whole scene so your manual drawing is also removed. The only way how you could keep something on the screen is if you created a Sprite in RMXP's scripts, created and assigned a Bitmap to it and drew your stuff on that Bitmap. Obviously the sprite should have a high z coordinate to always appear over all the other sprites.
You do it all in RMXP. You don't need the Win32 API for that.
What are you actually trying to do? If you just want something to be visible on the screen all the time, you can really make that work with just a simple sprite.
Alright, I'll just use the built in bitmap methods for mine.