Directx 9 - is the SetScissorRect behavior same for surfaces? - c++

First off, i need to use directx 9 for compatibility,
i started drawing a text with
RECT pos { 2, 2, 100, 100 };
if(!gfont)
D3DXCreateFont( iDev, 20, NULL, NULL, NULL, NULL, DEFAULT_CHARSET, NULL, ANTIALIASED_QUALITY, NULL, "Segoe UI Light", &gfont );
else
{
gfont->DrawText( NULL, "Sample", -1, &pos, NULL, D3DCOLOR_ARGB( 255, 0, 255, 255 ) );
}
and it's all right, i get:
so if we add SetScissorRect
RECT protectedRect { 2, 2, 50, 50 };
iDev->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
iDev->SetScissorRect( &protectedRect );
i get:
which it's the right result, now if i do with surfaces, the surface it's loaded with D3DXLoadSurfaceFromFile() and allocated with CreateOffscreenPlainSurface() from a jpg file...
iDev->GetBackBuffer(NULL, NULL, D3DBACKBUFFER_TYPE_MONO, &backBuffsfc);
iDev->UpdateSurface(sfc, NULL, backBuffsfc, NULL);
RECT protectedRect { 2, 2, 50, 50 };
iDev->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
iDev->SetScissorRect( &protectedRect );
the surface keeps appearing completely like
the question is, why is not clipped like the text?

Related

Win32 - Button images appear in wrong order in toolbar

I am creating a simple Paint application using win32 api (in visual studio). I have created a toolbar and added a bitmap for 10 toolbar images (TBbuttons.bmp - size: 160x16 pixel - 4bpp indexed format) as below:
However the button images do not appear in the correct order as shown above and, moreover, some images have a black line above them (which is not what i intended):
Here is the code i use to create the toolbar as well as those buttons:
InitCommonControls();
//create initial buttons
TBBUTTON tbButtons[] =
{
{ STD_FILENEW, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{ STD_FILEOPEN, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{ STD_FILESAVE, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}
};
//Create toolbar window
HWND hToolBarWnd = CreateToolbarEx(hWndParent,
WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | TBSTYLE_TOOLTIPS,
ID_TOOLBAR, sizeof(tbButtons) / sizeof(TBBUTTON), HINST_COMMCTRL,
0, tbButtons, sizeof(tbButtons) / sizeof(TBBUTTON),
BUTTON_WIDTH, BUTTON_HEIGHT, IMAGE_WIDTH, IMAGE_HEIGHT,
sizeof(TBBUTTON));
//Add more buttons
TBBUTTON buttonsToAdd[] =
{
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0 },
{ STD_CUT, IDM_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ STD_COPY, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ STD_PASTE, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ STD_DELETE, IDM_DELETE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }
};
SendMessage(hToolBarWnd, TB_ADDBUTTONS, (WPARAM)sizeof(buttonsToAdd) / sizeof(TBBUTTON),
(LPARAM)(LPTBBUTTON)&buttonsToAdd);
//Create 10 more buttons to draw
TBBUTTON userButtons[] =
{
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0 },
{ 0, IDM_ELLIPSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 1, IDM_FILLED_ELLIPSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 2, IDM_RECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 3, IDM_FILLED_RECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 4, IDM_CIRCLE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 5, IDM_FILLED_CIRCLE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 6, IDM_SQUARE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 7, IDM_FILLED_SQUARE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 8, IDM_LINE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 },
{ 9, IDM_TEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }
};
TBADDBITMAP tbBitmap = { hInst, IDB_BITMAP1 };
//Add bitmap to toolbar
int idx = SendMessage(hToolBarWnd, TB_ADDBITMAP, (WPARAM)sizeof(tbBitmap) / sizeof(TBADDBITMAP),
(LPARAM)(LPTBADDBITMAP)&tbBitmap);
for (int i = 1; i <= 10; i++) {
userButtons[i].iBitmap += idx;
}
//Add button to toolbar
SendMessage(hToolBarWnd, TB_ADDBUTTONS, (WPARAM)sizeof(userButtons) / sizeof(TBBUTTON),
(LPARAM)(LPTBBUTTON)&userButtons);
I am still new to win32 api and i have no idea what is the cause of this. The application still runs fine but the buttons images are completely wrong. How can i fix this? Is it because of my code or the bitmap i created that caused the issue?
EDIT: I added a new bitmap i found from the Internet (TBbitmap2.bmp) as a test and created anew another bitmap (TBbitmap3.bmp) similar to the first one. Of all 3 bitmaps, the first one produced the problem in the question and the other 2 bitmaps worked fine. Here is the link to all 3 bitmaps. The question remains why the first bitmap kept producing the problem but the other 2 worked? (they have the same properties just different size).
I tried to create a sample and used the bitmap.
It does have some weird behavior. After I built the project for the first time, it did produce the problem you said. But after I rebuilt, the problem disappeared:
I think the bitmap was not loaded correctly during the build process, maybe you can try to rebuild the project and run the program.

Toolbar / CreateToolbarEx problem C++ doesn't display all bitmaps

Renders only 4 images with sperator instead of the whole 9 total with 2 separators, no idea what causes it the code looks great.
Here is my code.
void CreateMacroToolBar(HWND hDlg)
{
// Load and register Toolbar control class
INITCOMMONCONTROLSEX iccx;
iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC = ICC_BAR_CLASSES;
if (!InitCommonControlsEx(&iccx))
return;
const DWORD buttonStyles = TBSTYLE_AUTOSIZE | TBSTYLE_BUTTON;
const DWORD TOOLBAR_STYLE = WS_CHILD | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE |
CCS_NOPARENTALIGN |
CCS_NORESIZE |
CCS_NODIVIDER;
// Declare and initialize local constants.
const int numButtons = 7;
const int numButtonsTotal = 9;
TBBUTTON tbButtons[numButtonsTotal] =
{
{ 0, IDM_BUTTON_MACRO_RECORD, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)(L"Record a macro" },
{ 1, IDM_BUTTON_MACRO_STOP, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Stop recording" },
{ 2, IDM_BUTTON_MACRO_PLAY, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Play macro" },
{ I_IMAGENONE, -1, 0, TBSTYLE_SEP, {0}, 0, -1}, //SEPERATOR
{ 3, IDM_BUTTON_MACRO_ERASE, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Erase the macro" },
{ 4, IDM_BUTTON_MACRO_LOAD, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Load a macro" },
{ 5, IDM_BUTTON_MACRO_SAVE, 0, buttonStyles, {0}, 0, (INT_PTR)(L"Save a macro" },
{ I_IMAGENONE, -1, 0, TBSTYLE_SEP, {0}, 0, -1}, //SEPERATOR
{ 6, IDM_MACRO_ABOUTBOX, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"About macro options" }
};
RECT rect;
HWND hwndTB;
hwndTB = CreateToolbarEx (GetDlgItem(hDlg, IDC_STATIC_TOOLBAR_MACRO), //Apply toolbar to static text.
TOOLBAR_STYLE, //Toolbar style.
ID_MACRO_TOOLBAR, //Toolbar ID.
numButtons, //Button of buttons (bmp's) (without seperators)
hDLLModule, //Current application instance (where the bitmap is)
IDR_TOOLBAR_MACRO, //Bitmap ID.
tbButtons, //Buttons struct
numButtonsTotal, //Total buttons (with seperators)
16, 15, 16, 15, //Button sizes and Bitmap sizes.
sizeof(TBBUTTON) );
if (!hwndTB) {
printf("Loading Macros failed!\n");
return;
}
//SendMessage(hwndTB, TB_AUTOSIZE, 0, 0); //Auto size to show more toolbars TODO: [DOESN'T WORK]
SendMessage(hwndTB, TB_SETMAXTEXTROWS, 0, 0); //Removes the label from Toolbar and adds Tooltips.
}
my IDE setup
my toolbar bitmap spliced image looks good
Here is how the bitmap looks in bitmap file .bmp (not the white area isn't accounted for I just did a bad print screen)
Here is how the static text looks like where it gets rendered
Here is how the static text Properties looks like where the toolbar gets rendered
Finished product when loading looks like this, note it only loads up the first 4 icons + 1 separator total of 5
Instead of 9 as needed with separators, or 7 if it loads only the images
A toolbar's height is determined by the height of the buttons, and a toolbar's width is the same as the width of the parent window's client area, also by default. In this case you have passed GetDlgItem(hDlg, IDC_STATIC_TOOLBAR_MACRO) this is likely the static label. Which would limit the width of the toolbar to the width of that static control. I believe if you pass hDlg as the first parameter to CreateToolbarEx it will resolve your issue. Or create a new window to contain it that's large enough, who's parent is hDlg.
Removing these 2 styles from all buttons fixes the problem.
CCS_NOPARENTALIGN | CCS_NORESIZE

Want some text to erase its self in game

Ok so just kind of want to know a trick to get around this.
So i want the text "window will close in 10 seconds" to erase every time it goes through the loop and replace with the next number counting down. But all i get now is overlapping.
I just want it to count down and display as it goes.
//FILE: Main.cpp
//PROGR: Hank Bates
//PURPOSE: To display text on screen for 10 seconds.
//EXTRA ADD ON FILES: Slendermanswriting.ttf
// PrometheusSiren.wav
#include <allegro5\allegro.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
#include <allegro5\allegro_native_dialog.h>
#include <allegro5\allegro_audio.h>
#include <allegro5\allegro_acodec.h>
int main(void)
{
//summon the fonts and stuff
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_FONT *font50;
ALLEGRO_FONT *font36;
ALLEGRO_FONT *font18;
ALLEGRO_SAMPLE *song;
int a = 100;
if (!al_init())
{
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize allegro!", NULL, NULL);
return -1;
}
//set up some of the display settings
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
display = al_create_display(640, 480);
al_set_window_title(display, "A bad horror game");
if (!display)
{
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize display!", NULL, NULL);
return -1;
}
al_init_font_addon();
al_init_ttf_addon();
//Install Slender Man font here
font50 = al_load_font("Slendermanswriting.ttf", 50, 0);
font36 = al_load_font("Slendermanswriting.ttf", 36, 0);
font18 = al_load_font("Slendermanswriting.ttf", 18, 0);
//set up music here
al_install_audio();
al_init_acodec_addon();
al_reserve_samples(1);
song = al_load_sample("PrometheusSiren.wav");
//play song this will loop around and around like a record man!
al_play_sample(song, 1, 0, 1, ALLEGRO_PLAYMODE_LOOP, NULL);
int screen_w = al_get_display_width(display);
int screen_h = al_get_display_height(display);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_text(font50, al_map_rgb(255, 0, 0), 12, 50, 0, "SLENDER MAN IS COMING");
al_draw_text(font36, al_map_rgb(255, 5, 10), 200, 100, 0, "RUN AND HIDE");
al_draw_text(font18, al_map_rgb(100, 15, 18), 150, 150, 0, "ENJOY THE PROMETHEUS SIREN MUSIC");
int timer = 10;
while (timer != 0)
{
al_draw_textf(font18, al_map_rgb(255, 255, 255), screen_w / 3, 300, ALLEGRO_ALIGN_CENTRE,
"TURN UP YOUR VOLUME TO %i PRECENT!", a);
al_draw_textf(font18, al_map_rgb(255, 255, 255), screen_w / 2, 400, ALLEGRO_ALIGN_CENTRE,
"WINDOW WILL CLOSE IN %i seconds!", timer);
al_flip_display();
al_rest(1.0);
timer = timer - 1;
}
al_rest(10.0);
//destroy stuff
al_destroy_font(font18);
al_destroy_font(font50);
al_destroy_font(font36);
al_destroy_display(display);
al_destroy_sample(song);
//pew pew pew, bang.... all destoryed :)
return 0;
}
Move the background clear and first three text outputs into the main loop. You need to redraw everything on each frame.
//FILE: Main.cpp
//PROGR: Hank Bates
//PURPOSE: To display text on screen for 10 seconds.
//EXTRA ADD ON FILES: Slendermanswriting.ttf
// PrometheusSiren.wav
#include <allegro5\allegro.h>
#include <allegro5\allegro_font.h>
#include <allegro5\allegro_ttf.h>
#include <allegro5\allegro_native_dialog.h>
#include <allegro5\allegro_audio.h>
#include <allegro5\allegro_acodec.h>
int main(void)
{
//summon the fonts and stuff
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_FONT *font50;
ALLEGRO_FONT *font36;
ALLEGRO_FONT *font18;
ALLEGRO_SAMPLE *song;
int a = 100;
int time_left = 10;
//test redaw
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer = NULL;
bool redraw = true;
if (!al_init())
{
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize allegro!", NULL, NULL);
return -1;
}
//set up some of the display settings
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE);
display = al_create_display(640, 480);
al_set_window_title(display, "A bad horror game");
if (!display)
{
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize display!", NULL, NULL);
return -1;
}
al_init_font_addon();
al_init_ttf_addon();
//Install Slender Man font here
font50 = al_load_font("Slendermanswriting.ttf", 50, 0);
font36 = al_load_font("Slendermanswriting.ttf", 36, 0);
font18 = al_load_font("Slendermanswriting.ttf", 18, 0);
//set up music here
al_install_audio();
al_init_acodec_addon();
al_reserve_samples(1);
//upload the song here
song = al_load_sample("PrometheusSiren.wav");
//play song this will loop around and around like a record man!
al_play_sample(song, 1, 0, 1, ALLEGRO_PLAYMODE_LOOP, NULL);
int screen_w = al_get_display_width(display);
int screen_h = al_get_display_height(display);
al_clear_to_color(al_map_rgb(0, 0, 0));
while (time_left != 0)
{
al_flip_display();
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_text(font50, al_map_rgb(255, 0, 0), 12, 50, 0, "SLENDER MAN IS COMING");
al_draw_text(font36, al_map_rgb(255, 5, 10), 200, 100, 0, "RUN AND HIDE");
al_draw_text(font18, al_map_rgb(100, 15, 18), 150, 150, 0, "ENJOY THE PROMETHEUS SIREN MUSIC");
al_draw_textf(font18, al_map_rgb(255, 255, 255), screen_w / 3, 300, ALLEGRO_ALIGN_CENTRE,
"TURN UP YOUR VOLUME TO %i PRECENT!", a);
al_draw_textf(font18, al_map_rgb(255, 255, 255), screen_w / 2, 400, ALLEGRO_ALIGN_CENTRE,
"WINDOW WILL CLOSE IN %i seconds!", time_left);
al_rest(1.0);
time_left = time_left - 1;
}
al_flip_display();
al_rest(0.0);
//destroy stuff
al_destroy_font(font18);
al_destroy_font(font50);
al_destroy_font(font36);
al_destroy_display(display);
al_destroy_sample(song);
al_destroy_timer(timer);
//pew pew pew, bang.... all destoryed :)
return 0;
}
Yo i got it. Thanks for the point in the right question.

How to clear drawing area for ActiveX OCX control?

I have some trouble drawing an ActiveX control. In the screenshot below you see the control after a resize in the VB6 IDE. The control's outline from before the resize is still shown on the left-hand side of the control:
Here is the code that draws a black ellipsis with a red Z:
void CzFileIoXCtrl::OnDraw(CDC* pdc,
const CRect& rcBounds,
const CRect& rcInvalid)
{
if (!pdc)
{
return;
}
pdc->SetBkMode(TRANSPARENT);
pdc->SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));
pdc->Ellipse(rcBounds.left, rcBounds.top,
rcBounds.left + rcBounds.Width(),
rcBounds.top + rcBounds.Height());
HFONT font = CreateFont(int(rcBounds.Height() * 0.7),
int(rcBounds.Width() * 0.5),
0, 0, FW_BLACK, FALSE, FALSE, FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
FF_DECORATIVE, NULL);
pdc->SelectObject(font);
pdc->SetTextColor(RGB(255, 0, 0));
DRAWTEXTPARAMS params = { sizeof(DRAWTEXTPARAMS), 1, 0, 0, 1 };
RECT bounds = rcBounds;
CString z(L"Z");
pdc->DrawTextEx(z, &bounds, DT_CENTER | DT_VCENTER | DT_SINGLELINE, &params);
}
How can I clear the drawing area?
I managed to reproduce this in the vb form editor. It looks like the problem comes because you do not draw anything outside the ellipse. So, you can draw a rectangle in the entire area like this before drawing anything in OnDraw().
pdc->FillRect( rcBounds, &CBrush(TranslateColor( AmbientBackColor() )) );
I tested this and is working fine.

Trying to create HIMAGELIST, what am I doing wrong here?

I want to create an HIMAGELIST for the list view. It actually needs to consist of file icons.
Here's the code I have:
HIMAGELIST imageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
ILC_MASK, 1, 1);
HICON ico = reinterpret_cast<HICON>(LoadImage(0,IDI_APPLICATION,
IMAGE_ICON,0,0,LR_SHARED));
ImageList_AddIcon(imageList, ico);
ListView_SetImageList(listView, imageList, LVSIL_SMALL);
The list view with three elements now has three application items.
However when I try to add another icon (IDI_HAND in this case), I still get the same 3 icons.
Another problem I have is that I can't fetch the actual file icons I need:
SHFILEINFO sfi;
SHGetFileInfo (L"C:\\test.txt", NULL, &sfi, sizeof (sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
ImageList_AddIcon(imageList, sfi.hIcon);
This results in empty icons, not the txt icons I want.
I've been struggling with this for ever, and I greatly appreciate your help here.
UPDATE
I'm using sample code I found on the Internet to fill the list view (obviously that's not what I want):
UINT columnMask = LVCF_TEXT|LVCF_FMT|LVCF_SUBITEM|LVCF_WIDTH;
LVCOLUMN lc[] = {
{ columnMask, 0, 150, L"Text...",0, 0,0,0 },
{ columnMask, LVCFMT_CENTER, 70, L"Number",0, 1,0,0 },
{ columnMask, 0, 100, L"Whatever",0, 2,0,0 },
};
ListView_InsertColumn(listView, 0, &lc[0]);
ListView_InsertColumn(listView, 1, &lc[1]);
ListView_InsertColumn(listView, 2, &lc[2]);
UINT itemMask = LVIF_TEXT;
LVITEM li[] = {
{ itemMask, 0,0, 0,0, L"...for the first item!",0, 0,0,0,0,0,0 },
{ itemMask, 0,1, 0,0, L"1",0, 0,0,0,0,0,0 },
{ itemMask, 0,2, 0,0, L"14 bucks",0, 0,0,0,0,0,0 },
{ itemMask, 1,0, 0,0, L"...for the second item!",0, 0,0,0,0,0,0 },
{ itemMask, 1,1, 0,0, L"24",0, 0,0,0,0,0,0 },
{ itemMask, 1,2, 0,0, L"2 suns",0, 0,0,0,0,0,0 },
{ itemMask, 2,0, 0,0, L"...for the second item!",0, 0,0,0,0,0,0 },
{ itemMask, 2,1, 0,0, L"24",0, 0,0,0,0,0,0 },
{ itemMask, 2,2, 0,0, L"2 suns",0, 0,0,0,0,0,0 },
{ itemMask, 3,0, 0,0, L"...for the second item!",0, 0,0,0,0,0,0 },
{ itemMask, 3,1, 0,0, L"24",0, 0,0,0,0,0,0 },
{ itemMask, 3,2, 0,0, L"2 suns",0, 0,0,0,0,0,0 },
};
// setting an icon like this doesn't work
li[0].iImage = sfi.iIcon;
ListView_InsertItem(listView, &li[0]);
ListView_SetItem(listView, &li[1]);
ListView_SetItem(listView, &li[2]);
ListView_InsertItem(listView, &li[3]);
ListView_SetItem(listView, &li[4]);
ListView_SetItem(listView, &li[5]);
ListView_InsertItem(listView, &li[6]);
ListView_SetItem(listView, &li[7]);
ListView_SetItem(listView, &li[8]);
The iImage member of LVICON is the index of the icon in the imagelist you passed to ListView_SetImageList. You are passing the index of the icon in the system imagelist, but the imagelist you passed to ListView_SetImageList is your private imagelist. Either
Use ListView_SetImageList to associate the imagelist with your private imagelist, and set the iImage to the index in your private imagelist (the return value from ImageList_AddIcon)
Use ListView_SetImageList to associate the imagelist with the system imagelist, and set the iImage to the index in the system imagelist.
For your second problem, try passing just the .extension, in your case pass .txt as the first param, and these flags: SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES or SHGFI_SMALLICON or SHGFI_ICON and on return, sfi.hIcon should contain the handle of the txt file icon
Without SHGFI_ICON, SHGetFileInfo is just filling in sfi.iIcon which is the index of the icon in the system imagelist, by adding SHGFI_ICON, SHGetFileInfo will also fill in sfi.hIcon which is what you want.
How are you adding the listview items? Show the code where you fill in the LVITEM structure.