Hello everybody,
The function used to insert the items is in a thread.
The goal is to display images of all files in a folder.
When the function ends I can see all the images.I use LVM_INSERTITEM to insert data into a ListView
LVM_INSERTITEM always returns 0 as index item.
So I use LVM_FINDITEM with lParam set to the lParam item of the LVITEM structure.
LVM_FINDITEM returns -1
I need some help please about this.
MOV _LvFind.flags,LVFI_PARAM
MOV RCX,[hLvImageList + RIP]
MOV RDX,RAX
XOR R8D,R8D
CALL ImageList_Add
MOV _Lvi.iImage ,EAX
MOV _ImageInfos.IndexImageList,EAX
LEA RAX,_ImageInfos.szImageFile
MOV _Lvi._mask,LVIF_DI_SETITEM OR LVIF_IMAGE OR LVIF_NORECOMPUTE OR LVIF_PARAM OR LVIF_TEXT
MOV _Lvi.pszText,RAX
MOV EAX,_iRecNo
MOV _Lvi.lParam,RAX
LEA RCX,_ImageInfos.szImageFile
CALL PathFindFileNameA
MOV RCX,[hListView + RIP]
MOV RDX,LVM_INSERTITEM
XOR R8D,R8D
LEA R9,_Lvi
MOV [R9].LVITEM.pszText,RAX
CALL SendMessageA
MOV _Lvi.iItem,EAX
MOV RAX,[_Lvi.lParam]
MOV _LvFind.lParam,RAX
MOV RCX,[hListView + RIP]
MOV RDX,LVM_FINDITEM
MOV R8D,0
LEA R9,_LvFind
CALL SendMessageA
GUI messages should be in the same thread that created the window, if I well remember, when sending message from a different thread you should use PostMessage().
See this link. (https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagea)
I replaced SendMessage with PostMessage and now LVM_INSERTITEM always returns 1!
Well, it happened that I remembered wrong ;D
Not at all sure, but are you setting the iSubItem to 0? LVM_INSERTITEM can't be used to insert subitems.
John Z
John the insertion works well.
Frankie, you were right, I saw the link, I don't understand.
I have too many problems with this program and I will remake it.
Works well with 500 images and problems appear witn 5000 images to display.
Perhaps a problem with SQLite (SQL_BUSY)
Now I am making an other analysis including the problems I met.
A suggestion that I can give you is to handle whole GUI stuff in the same thread (that is the standard approach).
Other threads will place requests for GUI actions using shared objects (variables, buffers) or interthread communication. ;)
About the SQLite consider that each SQL will open and modify the whole database file, and this is very slow, unless you explicitly use transactions (see this link (https://sqlite.org/lang_transaction.html)).
Use:
BEGIN TRANSACTION;
..... --Many SQLs
COMMIT TRANSATION;
In this case SQLite will prepare all SQLs in memory and commit them in a single file update when encounters the "COMMIT".
In your program prepare and execute the SQL: "BEGIN TRANSACTION;".
Then run all code that executes other SQLs logically grouped, the prepare and execute the SQL "COMMIT TRANSATION;" to update database file.
What I did before but the program is too slow in that case.
Thank You for the idea.
I have not tried that but if I create the listview in the same thread that the one used for filling it?
I could use SendMessage.
Quote from: Grincheux on July 04, 2021, 09:30:22 PM
I have not tried that but if I create the listview in the same thread that the one used for filling it?
I could use SendMessage.
You can have a bigger problem because the message loop have to be created also in the new thread, and I don't think that this is what you want.
I don't understand why you say that the program is slow. That is the standard way to produce GUI software. Maybe the problem was somewhere else?
I updated my previous message with some info for SQLite.
To improve list view performance for a large number of items have you used LVM_SETITEMCOUNT?
Set to a large number to improve performance. The data structure will not need allocate for every addition.
John Z
To improve performance, you can also try the following:
// right before inserting items into list
SendMessage ( hList, WM_SETREDRAW, FALSE, 0 );
// .. insert a bunch of items into list
...
...
// finished updating the list, tell it that's ok to redraw now
SendMessage ( hList, WM_SETREDRAW, TRUE, 0 );
InvalidateRect ( hList, NULL, TRUE );
What this does is that it basically tells the listview to disable all scrollbar and item position calculations until you've finished adding all entries to it.
It should have a noticeable effect.
Those WM_SETREDRAW messages should be sent in the main thread.
JohnZ and algernon_77 I will try your devices.
Frankie
Quote[size=0px]You can have a bigger problem because the message loop have to be created also in the new thread, and I don't think that this is what you want.[/size]
Yes, that's what I had discovered, but too late I already posted my message.
It is like there was a SORT command, the item always is 0 until it is sorted.
QuoteBEGIN TRANSACTION;
I know that a transation is a way to be faster, but you also can change some pragmas to be quicker too.void SQLite3Pragmas(sqlite3 *__hSqlite)
{
sqlite3_exec(__hSqlite,"PRAGMA wal_autocheckpoint = 0",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA encoding = \"UTF-8\"",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA cache_spill=FALSE;",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA temp_store = MEMORY",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA case_sensitive_like = TRUE",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA foreign_keys = OFF",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA legacy_file_format = OFF",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA cache_size = -2000",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.cache_size = -2000",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.auto_vacuum = NONE",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.journal_mode = OFF",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.secure_delete = OFF",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.synchronous = OFF",0,0,NULL) ; // This one is very efficient for SPEED
sqlite3_exec(__hSqlite,"PRAGMA main.locking_mode = EXCLUSIVE",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.user_version = 23072014",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA main.application_id = 24121959",0,0,NULL) ;
sqlite3_exec(__hSqlite,"PRAGMA shrink_memory",0,0,NULL) ;
return ;
}
The problem is how to manage SQLITE_BUSY, if SQLITE_BUSY is returned with a transaction that upgrades the database, you can restart the upgrade,if it is a transaction that inserts records, it is less easy. We have to use something like the following:"INSERT OR IGNORE INTO [Hashes]([Hash],[BaseCrc64],[Crc64],[Password]) VALUES (\"%s\",%llu,%llu,\"%w\")" ;
Thank you JohnZ, Frankie & alger_non77 for your help.
Here is a link on the project (ASM Source code and C Source code) + Binaries
Many problems have been solved (one part with your help)
https://www.mediafire.com/file/pt8i7v2vo6eqers/Display.7z/file (https://www.mediafire.com/file/pt8i7v2vo6eqers/Display.7z/file)
I am thinking about a "rename option" that would use the last sort to rename the files like this: [Folder Name]-[0000-nnnn].jpg
but for the instant I must correct bugs and improve the source code, remove dead code...
To install the program just copy it into a folder of your choice, once launched the program creates 2 folders (Datas and Settings).
You must copy the 3 DLLs too : libgfle340.dll + libgfl340.dll + sqlite3.dll
Thank You I have appreciated your help : JohnZ, Frankie and algernon_77
Adventurously, I'll give it a go. :)
Thank you for sharing it.
John Z