Я использую это с несколькими вариантами выбора. Он также работает с чередующимися выделениями.
private void Order_buttons_Click(object sender, EventArgs e)
{
//If noselection return
if (Layouts_listBox.SelectedItems.Count == 0) return;
//Determines wether up or down
int movement = (sender as Button) == Order_Upbutton? - 1 : 1;
//creates a dictionary associating the original Index (ListBox) to the text
Dictionary<int, string> Items = new Dictionary<int, string>();
//Also creates a list with the Index for sorting
List<int> DesiredOrder = new List<int>();
//Cycle through the selection and fill both the list and dictionary
ListBox.SelectedObjectCollection NN = Layouts_listBox.SelectedItems;
foreach (object n in NN)
{
DesiredOrder.Add(Layouts_listBox.Items.IndexOf(n));
Items.Add(Layouts_listBox.Items.IndexOf(n), (string)n);
}
//Sort the List according to the desired button (Up or Down)
DesiredOrder.Sort();
if ((sender as Button) != Order_Upbutton) DesiredOrder.Reverse();
//I'm using this ErrorHandling but thats up to you
try
{
//Call the MoveItem (Credits to Save) according to the sorted order
foreach (int n in DesiredOrder) MoveItem(movement, Items[n]);
}
catch (Exception)
{
SystemSounds.Asterisk.Play();
}
}
public void MoveItem(int direction, string Selected)
{
// Checking selected item
if (!Layouts_listBox.Items.Contains(Selected) || Layouts_listBox.Items.IndexOf(Selected) < 0)
throw new System.Exception(); // No selected item - Cancel entire Func
// Calculate new index using move direction
int newIndex = Layouts_listBox.Items.IndexOf(Selected) + direction;
// Checking bounds of the range
if (newIndex < 0 || newIndex >= Layouts_listBox.Items.Count)
throw new System.Exception(); // Index out of range - Cancel entire Func
object selected = Layouts_listBox.Items[Layouts_listBox.Items.IndexOf(Selected)];
// Removing removable element
Layouts_listBox.Items.Remove(selected);
// Insert it in new position
Layouts_listBox.Items.Insert(newIndex, selected);
// Restore selection
Layouts_listBox.SetSelected(newIndex, true);
}
Итак, я действительно делаю это в одном из моих проектов.
Во-первых, библиотека должна быть собрана с помощью ADD_LIBRARY (), но я предполагаю, что вы делаете это. Что-то вроде
ADD_LIBRARY (${MyLibName} ${SOURCES})
в CMakeLists.txt библиотеки
, которое добавляет библиотеку в список библиотек cmake.
Во-вторых, вы добавляете библиотеку в свой проект с помощью
target_link_libraries (${PROJECT_NAME} ${MyLibName})
в CMakeLists.txt исполняемого файла, того же, где у вас есть add_executable (${PROJECT_NAME} ${SOURCES})
, который будет настраивать цепочка зависимостей для принудительного создания MyLibName перед PROJECT_NAME.
При условии, что в описанном проекте только заголовочные файлы в каталоге mylib/include
должны считаться общедоступными:
Верхний уровень CMakeLists.txt
для mylib
должен содержать:
Это гарантирует, что проекты, включающие mylib
, будут иметь доступ только к файлам в каталоге include/
. Файлы в include/
могут использоваться как #include <myfile.h>
, а файлы в include/mylib
(общее соглашение) могут использоваться как #include <mylib/myfile.h>
.
Верхний уровень CMakeLists.txt
для myapp
должен включать:
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(myapp VERSION 0.1 LANGUAGES CXX)
add_subdirectory(libs/mylib)
add_executable(${MyAppName} ${MyApp_SOURCES})
target_link_libraries(${MyAppName} ${MyLibName}
Использование add_subdirectory
гарантирует, что mylib
будет построено до myapp
, а target_link_libraries
добавляет [ 1117] к исполняемому файлу.
Как упоминал Цалумэн, обязательно посмотрите учебники по CMake и предпочитаете использовать cmake --build .
вместо make
.